100 fun add_stmt sym stmt = |
100 fun add_stmt sym stmt = |
101 let |
101 let |
102 val (module_name, base) = prep_sym sym; |
102 val (module_name, base) = prep_sym sym; |
103 in |
103 in |
104 Graph.default_node (module_name, (Code_Symbol.Graph.empty, [])) |
104 Graph.default_node (module_name, (Code_Symbol.Graph.empty, [])) |
105 #> (Graph.map_node module_name o apfst) (Code_Symbol.Graph.new_node (sym, (base, (true, stmt)))) |
105 #> (Graph.map_node module_name o apfst) |
|
106 (Code_Symbol.Graph.new_node (sym, (base, (true, stmt)))) |
106 end; |
107 end; |
107 fun add_dep sym sym' = |
108 fun add_dep sym sym' = |
108 let |
109 let |
109 val (module_name, _) = prep_sym sym; |
110 val (module_name, _) = prep_sym sym; |
110 val (module_name', _) = prep_sym sym'; |
111 val (module_name', _) = prep_sym sym'; |
111 in if module_name = module_name' |
112 in if module_name = module_name' |
112 then (Graph.map_node module_name o apfst) (Code_Symbol.Graph.add_edge (sym, sym')) |
113 then (Graph.map_node module_name o apfst) (Code_Symbol.Graph.add_edge (sym, sym')) |
113 else (Graph.map_node module_name o apsnd) (AList.map_default (op =) (module_name', []) (insert (op =) sym')) |
114 else (Graph.map_node module_name o apsnd) |
|
115 (AList.map_default (op =) (module_name', []) (insert (op =) sym')) |
114 end; |
116 end; |
115 val proto_program = build_proto_program |
117 val proto_program = build_proto_program |
116 { empty = Graph.empty, add_stmt = add_stmt, add_dep = add_dep } program; |
118 { empty = Graph.empty, add_stmt = add_stmt, add_dep = add_dep } program; |
117 |
119 |
118 (* name declarations and statement modifications *) |
120 (* name declarations and statement modifications *) |
123 in (gr', nsp') end; |
125 in (gr', nsp') end; |
124 fun declarations gr = (gr, empty_nsp) |
126 fun declarations gr = (gr, empty_nsp) |
125 |> fold (fn sym => declare sym (Code_Symbol.Graph.get_node gr sym)) |
127 |> fold (fn sym => declare sym (Code_Symbol.Graph.get_node gr sym)) |
126 (prioritize sym_priority (Code_Symbol.Graph.keys gr)) |
128 (prioritize sym_priority (Code_Symbol.Graph.keys gr)) |
127 |> fst |
129 |> fst |
128 |> (Code_Symbol.Graph.map o K o apsnd) |
130 |> Code_Symbol.Graph.map_strong_conn (fn syms_bases_exports_stmts => |
129 (fn (export, stmt) => Option.map (pair export) (modify_stmt stmt)); |
131 map snd syms_bases_exports_stmts |
|
132 |> (map o apsnd) (fn (export, stmt) => Option.map (pair export) (modify_stmt stmt))); |
130 val flat_program = proto_program |
133 val flat_program = proto_program |
131 |> (Graph.map o K o apfst) declarations; |
134 |> (Graph.map o K o apfst) declarations; |
132 |
135 |
133 (* qualified and unqualified imports, deresolving *) |
136 (* qualified and unqualified imports, deresolving *) |
134 fun base_deresolver sym = fst (Code_Symbol.Graph.get_node |
137 fun base_deresolver sym = fst (Code_Symbol.Graph.get_node |
175 fun map_module [] = I |
178 fun map_module [] = I |
176 | map_module (name_fragment :: name_fragments) = |
179 | map_module (name_fragment :: name_fragments) = |
177 apsnd o Code_Symbol.Graph.map_node (Code_Symbol.Module name_fragment) o apsnd o map_module_content |
180 apsnd o Code_Symbol.Graph.map_node (Code_Symbol.Module name_fragment) o apsnd o map_module_content |
178 o map_module name_fragments; |
181 o map_module name_fragments; |
179 |
182 |
|
183 fun map_module_stmts f_module f_stmts sym_base_nodes = |
|
184 let |
|
185 val some_modules = |
|
186 sym_base_nodes |
|
187 |> map (fn (sym, (base, Module content)) => SOME (base, content) | _ => NONE) |
|
188 |> (burrow_options o map o apsnd) f_module; |
|
189 val some_export_stmts = |
|
190 sym_base_nodes |
|
191 |> map (fn (sym, (base, Stmt export_stmt)) => SOME ((sym, export_stmt), base) | _ => NONE) |
|
192 |> (burrow_options o burrow_fst) (fn [] => [] | xs => f_stmts xs) |
|
193 in |
|
194 map2 (fn SOME (base, content) => (K (base, Module content)) |
|
195 | NONE => fn SOME (some_export_stmt, base) => |
|
196 (base, case some_export_stmt of SOME export_stmt => Stmt export_stmt | NONE => Dummy)) |
|
197 some_modules some_export_stmts |
|
198 end; |
|
199 |
180 fun hierarchical_program ctxt { module_name, reserved, identifiers, empty_nsp, |
200 fun hierarchical_program ctxt { module_name, reserved, identifiers, empty_nsp, |
181 namify_module, namify_stmt, cyclic_modules, empty_data, memorize_data, modify_stmts } program = |
201 namify_module, namify_stmt, cyclic_modules, empty_data, memorize_data, modify_stmts } program = |
182 let |
202 let |
183 |
203 |
184 (* building module name hierarchy *) |
204 (* building module name hierarchy *) |
207 (* distribute statements over hierarchy *) |
227 (* distribute statements over hierarchy *) |
208 fun add_stmt sym stmt = |
228 fun add_stmt sym stmt = |
209 let |
229 let |
210 val (name_fragments, base) = prep_sym sym; |
230 val (name_fragments, base) = prep_sym sym; |
211 in |
231 in |
212 (map_module name_fragments o apsnd) (Code_Symbol.Graph.new_node (sym, (base, Stmt (true, stmt)))) |
232 (map_module name_fragments o apsnd) |
|
233 (Code_Symbol.Graph.new_node (sym, (base, Stmt (true, stmt)))) |
213 end; |
234 end; |
|
235 fun add_edge_acyclic_error error_msg dep gr = |
|
236 Code_Symbol.Graph.add_edge_acyclic dep gr |
|
237 handle Graph.CYCLES _ => error (error_msg ()) |
214 fun add_dep sym sym' = |
238 fun add_dep sym sym' = |
215 let |
239 let |
216 val (name_fragments, _) = prep_sym sym; |
240 val (name_fragments, _) = prep_sym sym; |
217 val (name_fragments', _) = prep_sym sym'; |
241 val (name_fragments', _) = prep_sym sym'; |
218 val (name_fragments_common, (diff, diff')) = |
242 val (name_fragments_common, (diff, diff')) = |
219 chop_prefix (op =) (name_fragments, name_fragments'); |
243 chop_prefix (op =) (name_fragments, name_fragments'); |
220 val is_module = not (null diff andalso null diff'); |
244 val is_cross_module = not (null diff andalso null diff'); |
221 val dep = pairself hd (map Code_Symbol.Module diff @ [sym], map Code_Symbol.Module diff' @ [sym']); |
245 val dep = pairself hd (map Code_Symbol.Module diff @ [sym], map Code_Symbol.Module diff' @ [sym']); |
222 val add_edge = if is_module andalso not cyclic_modules |
246 val add_edge = if is_cross_module andalso not cyclic_modules |
223 then (fn node => Code_Symbol.Graph.add_edge_acyclic dep node |
247 then add_edge_acyclic_error (fn _ => "Dependency " |
224 handle Graph.CYCLES _ => error ("Dependency " |
248 ^ Code_Symbol.quote ctxt sym ^ " -> " |
225 ^ Code_Symbol.quote ctxt sym ^ " -> " |
249 ^ Code_Symbol.quote ctxt sym' |
226 ^ Code_Symbol.quote ctxt sym' |
250 ^ " would result in module dependency cycle") dep |
227 ^ " would result in module dependency cycle")) |
251 else Code_Symbol.Graph.add_edge dep; |
228 else Code_Symbol.Graph.add_edge dep |
|
229 in (map_module name_fragments_common o apsnd) add_edge end; |
252 in (map_module name_fragments_common o apsnd) add_edge end; |
230 val proto_program = build_proto_program |
253 val proto_program = build_proto_program |
231 { empty = empty_program, add_stmt = add_stmt, add_dep = add_dep } program; |
254 { empty = empty_program, add_stmt = add_stmt, add_dep = add_dep } program; |
232 |
255 |
233 (* name declarations, data and statement modifications *) |
256 (* name declarations, data and statement modifications *) |
246 val nodes' = Code_Symbol.Graph.map_node sym (K (base', node)) nodes; |
269 val nodes' = Code_Symbol.Graph.map_node sym (K (base', node)) nodes; |
247 in (nsps', nodes') end; |
270 in (nsps', nodes') end; |
248 val (nsps', nodes') = (nsps, nodes) |
271 val (nsps', nodes') = (nsps, nodes) |
249 |> fold (declare (K namify_module)) module_fragments |
272 |> fold (declare (K namify_module)) module_fragments |
250 |> fold (declare (namify_stmt o snd o the_stmt)) stmt_syms; |
273 |> fold (declare (namify_stmt o snd o the_stmt)) stmt_syms; |
251 fun select_syms syms = case filter (member (op =) stmt_syms) syms |
274 fun modify_stmts' syms_stmts = |
252 of [] => NONE |
|
253 | syms => SOME syms; |
|
254 fun select_stmt (sym, (export, SOME stmt)) = SOME (sym, (export, stmt)) |
|
255 | select_stmt _ = NONE; |
|
256 fun modify_stmts' syms = |
|
257 let |
275 let |
258 val (exports, stmts) = map_split (the_stmt o snd o Code_Symbol.Graph.get_node nodes) syms; |
276 val stmts' = modify_stmts syms_stmts |
259 val stmts' = modify_stmts (syms ~~ stmts); |
277 in stmts' @ replicate (length syms_stmts - length stmts') NONE end; |
260 val stmts'' = stmts' @ replicate (length syms - length stmts') NONE; |
278 fun modify_stmts'' syms_exports_stmts = |
261 in map_filter select_stmt (syms ~~ (exports ~~ stmts'')) end; |
279 syms_exports_stmts |
262 val stmtss' = (maps modify_stmts' o map_filter select_syms o Code_Symbol.Graph.strong_conn) nodes; |
280 |> map (fn (sym, (export, stmt)) => ((sym, stmt), export)) |
263 val nodes'' = Code_Symbol.Graph.map (fn sym => apsnd (fn Module content => Module (make_declarations nsps' content) |
281 |> burrow_fst modify_stmts' |
264 | _ => case AList.lookup (op =) stmtss' sym of SOME stmt => Stmt stmt | _ => Dummy)) nodes'; |
282 |> map (fn (SOME stmt, export) => SOME (export, stmt) | _ => NONE); |
|
283 val nodes'' = |
|
284 nodes' |
|
285 |> Code_Symbol.Graph.map_strong_conn (map_module_stmts (make_declarations nsps') modify_stmts''); |
265 val data' = fold memorize_data stmt_syms data; |
286 val data' = fold memorize_data stmt_syms data; |
266 in (data', nodes'') end; |
287 in (data', nodes'') end; |
267 val (_, hierarchical_program) = make_declarations empty_nsp proto_program; |
288 val (_, hierarchical_program) = make_declarations empty_nsp proto_program; |
268 |
289 |
269 (* deresolving *) |
290 (* deresolving *) |