src/Tools/Code/code_haskell.ML
changeset 39202 dd0660d93c31
parent 39142 f63715f00fdd
child 39204 3d30f501b7c2
equal deleted inserted replaced
39154:14b16b380ca1 39202:dd0660d93c31
   259               str "};"
   259               str "};"
   260             ) (map print_classparam_instance classparam_instances)
   260             ) (map print_classparam_instance classparam_instances)
   261           end;
   261           end;
   262   in print_stmt end;
   262   in print_stmt end;
   263 
   263 
       
   264 type flat_program = ((string * Code_Thingol.stmt) Graph.T * ((string * (string list * string list)) list)) Graph.T;
       
   265 
       
   266 fun flat_program labelled_name { module_alias, module_prefix, reserved,
       
   267       empty_nsp, namify_stmt, modify_stmt } program =
       
   268   let
       
   269 
       
   270     (* building module name hierarchy *)
       
   271     val fragments_tab = Code_Namespace.build_module_namespace { module_alias = module_alias,
       
   272       module_prefix = module_prefix, reserved = reserved } program;
       
   273     val dest_name = Code_Namespace.dest_name
       
   274       #>> (Long_Name.implode o the o Symtab.lookup fragments_tab);
       
   275 
       
   276     (* distribute statements over hierarchy *)
       
   277     fun add_stmt name stmt =
       
   278       let
       
   279         val (module_name, base) = dest_name name;
       
   280       in case modify_stmt stmt
       
   281        of SOME stmt' => 
       
   282             Graph.default_node (module_name, (Graph.empty, []))
       
   283             #> (Graph.map_node module_name o apfst) (Graph.new_node (name, (base, stmt')))
       
   284         | NONE => I
       
   285       end;
       
   286     fun add_dependency name name' =
       
   287       let
       
   288         val (module_name, base) = dest_name name;
       
   289         val (module_name', base') = dest_name name';
       
   290       in if module_name = module_name'
       
   291         then (Graph.map_node module_name o apfst) (Graph.add_edge (name, name'))
       
   292         else (Graph.map_node module_name o apsnd)
       
   293           (AList.map_default (op =) (module_name', []) (insert (op =) name'))
       
   294       end;
       
   295     val proto_program = Graph.empty
       
   296       |> Graph.fold (fn (name, (stmt, _)) => add_stmt name stmt) program
       
   297       |> Graph.fold (fn (name, (_, (_, names))) => fold (add_dependency name) names) program;
       
   298 
       
   299     (* name declarations *)
       
   300     fun declare name (base, stmt) (gr, nsp) = 
       
   301       let
       
   302         val (base', nsp') = namify_stmt stmt base nsp;
       
   303         val gr' = (Graph.map_node name o apfst) (K base') gr;
       
   304       in (gr', nsp') end;
       
   305     fun declarations gr = (gr, empty_nsp)
       
   306       |> fold (fn name => declare name (Graph.get_node gr name)) (Graph.keys gr) 
       
   307       |> fst;
       
   308     val intermediate_program = proto_program
       
   309       |> Graph.map ((K o apfst) declarations);
       
   310 
       
   311     (* qualified and unqualified imports, deresolving *)
       
   312     fun base_deresolver name = fst (Graph.get_node
       
   313       (fst (Graph.get_node intermediate_program (fst (dest_name name)))) name);
       
   314     fun classify_imports gr imports =
       
   315       let
       
   316         val import_tab = maps
       
   317           (fn (module_name, names) => map (rpair module_name) names) imports;
       
   318         val imported_names = map fst import_tab;
       
   319         val here_names = Graph.keys gr;
       
   320         val qualified_names = []
       
   321           |> fold (fn name => AList.map_default (op =) (base_deresolver name, [])
       
   322                (insert (op =) name)) (here_names @ imported_names)
       
   323           |> filter (fn (_, names) => length names > 1)
       
   324           |> maps snd;
       
   325         val name_tab = Symtab.empty
       
   326           |> fold (fn name => Symtab.update (name, base_deresolver name)) here_names
       
   327           |> fold (fn name => Symtab.update (name,
       
   328                if member (op =) qualified_names name
       
   329                then Long_Name.append (the (AList.lookup (op =) import_tab name))
       
   330                  (base_deresolver name)
       
   331                else base_deresolver name)) imported_names;
       
   332         val imports' = (map o apsnd) (List.partition (member (op =) qualified_names))
       
   333           imports;
       
   334       in (name_tab, imports') end;
       
   335     val classified = AList.make (uncurry classify_imports o Graph.get_node intermediate_program)
       
   336       (Graph.keys intermediate_program);
       
   337     val flat_program = Graph.map (apsnd o K o snd o the o AList.lookup (op =) classified)
       
   338       intermediate_program;
       
   339     val deresolver_tab = Symtab.empty
       
   340       |> fold (fn (module_name, (name_tab, _)) => Symtab.update (module_name, name_tab)) classified;
       
   341     fun deresolver module_name name =
       
   342       the (Symtab.lookup (the (Symtab.lookup deresolver_tab module_name)) name)
       
   343       handle Option => error ("Unknown statement name: " ^ labelled_name name);
       
   344 
       
   345   in (deresolver, flat_program) end;
       
   346 
       
   347 fun haskell_program_of_program labelled_name module_alias module_prefix reserved =
       
   348   let
       
   349     fun namify_fun upper base (nsp_fun, nsp_typ) =
       
   350       let
       
   351         val (base', nsp_fun') = yield_singleton Name.variants
       
   352           (if upper then first_upper base else base) nsp_fun;
       
   353       in (base', (nsp_fun', nsp_typ)) end;
       
   354     fun namify_typ base (nsp_fun, nsp_typ) =
       
   355       let
       
   356         val (base', nsp_typ') = yield_singleton Name.variants
       
   357           (first_upper base) nsp_typ
       
   358       in (base', (nsp_fun, nsp_typ')) end;
       
   359     fun namify_stmt (Code_Thingol.Fun (_, (_, SOME _))) = pair
       
   360       | namify_stmt (Code_Thingol.Fun _) = namify_fun false
       
   361       | namify_stmt (Code_Thingol.Datatype _) = namify_typ
       
   362       | namify_stmt (Code_Thingol.Datatypecons _) = namify_fun true
       
   363       | namify_stmt (Code_Thingol.Class _) = namify_typ
       
   364       | namify_stmt (Code_Thingol.Classrel _) = pair
       
   365       | namify_stmt (Code_Thingol.Classparam _) = namify_fun false
       
   366       | namify_stmt (Code_Thingol.Classinst _) = pair;
       
   367     fun select_stmt (Code_Thingol.Fun (_, (_, SOME _))) = false
       
   368       | select_stmt (Code_Thingol.Fun _) = true
       
   369       | select_stmt (Code_Thingol.Datatype _) = true
       
   370       | select_stmt (Code_Thingol.Datatypecons _) = false
       
   371       | select_stmt (Code_Thingol.Class _) = true
       
   372       | select_stmt (Code_Thingol.Classrel _) = false
       
   373       | select_stmt (Code_Thingol.Classparam _) = false
       
   374       | select_stmt (Code_Thingol.Classinst _) = true;
       
   375   in
       
   376     flat_program labelled_name
       
   377       { module_alias = module_alias, module_prefix = module_prefix,
       
   378         reserved = reserved, empty_nsp = (reserved, reserved), namify_stmt = namify_stmt,
       
   379         modify_stmt = fn stmt => if select_stmt stmt then SOME stmt else NONE }
       
   380   end;
       
   381 
   264 fun mk_name_module reserved module_prefix module_alias program =
   382 fun mk_name_module reserved module_prefix module_alias program =
   265   let
   383   let
   266     fun mk_alias name = case module_alias name
   384     val fragments_tab = Code_Namespace.build_module_namespace { module_alias = module_alias,
   267      of SOME name' => name'
   385       module_prefix = module_prefix, reserved = reserved } program;
   268       | NONE => name
   386   in Long_Name.implode o the o Symtab.lookup fragments_tab end;
   269           |> Long_Name.explode
       
   270           |> map (fn name => (the_single o fst) (Name.variants [name] reserved))
       
   271           |> Long_Name.implode;
       
   272     fun mk_prefix name = case module_prefix
       
   273      of SOME module_prefix => Long_Name.append module_prefix name
       
   274       | NONE => name;
       
   275     val tab =
       
   276       Symtab.empty
       
   277       |> Graph.fold ((fn name => Symtab.default (name, (mk_alias #> mk_prefix) name))
       
   278            o fst o Code_Namespace.dest_name o fst)
       
   279              program
       
   280   in the o Symtab.lookup tab end;
       
   281 
   387 
   282 fun haskell_program_of_program labelled_name module_prefix reserved module_alias program =
   388 fun haskell_program_of_program labelled_name module_prefix reserved module_alias program =
   283   let
   389   let
   284     val reserved = Name.make_context reserved;
   390     val reserved = Name.make_context reserved;
   285     val mk_name_module = mk_name_module reserved module_prefix module_alias program;
   391     val mk_name_module = mk_name_module reserved module_prefix module_alias program;