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; |