17 -> (string -> string) -> (string -> string) -> string -> theory -> theory; |
17 -> (string -> string) -> (string -> string) -> string -> theory -> theory; |
18 val add_undefined: string -> string -> string -> theory -> theory; |
18 val add_undefined: string -> string -> string -> theory -> theory; |
19 val add_pretty_imperative_monad_bind: string -> string -> theory -> theory; |
19 val add_pretty_imperative_monad_bind: string -> string -> theory -> theory; |
20 |
20 |
21 type serializer; |
21 type serializer; |
22 val add_serializer : string * serializer -> theory -> theory; |
22 val add_serializer: string * serializer -> theory -> theory; |
23 val get_serializer: theory -> string -> Args.T list |
23 val get_serializer: theory -> string -> Args.T list -> (theory -> string -> string) |
24 -> string list option -> CodegenThingol.code -> unit; |
24 -> string list option -> CodegenThingol.code -> unit; |
25 val assert_serializer: theory -> string -> string; |
25 val assert_serializer: theory -> string -> string; |
26 |
26 |
27 val const_has_serialization: theory -> string list -> string -> bool; |
27 val const_has_serialization: theory -> string list -> string -> bool; |
28 val tyco_has_serialization: theory -> string list -> string -> bool; |
28 val tyco_has_serialization: theory -> string list -> string -> bool; |
29 |
29 |
30 val eval_verbose: bool ref; |
30 val eval_verbose: bool ref; |
31 val eval_term: theory -> CodegenThingol.code |
31 val eval_term: theory -> (theory -> string -> string) -> CodegenThingol.code |
32 -> (string * 'a option ref) * CodegenThingol.iterm -> 'a; |
32 -> (string * 'a option ref) * CodegenThingol.iterm -> 'a; |
33 val code_width: int ref; |
33 val code_width: int ref; |
34 end; |
34 end; |
35 |
35 |
36 structure CodegenSerializer: CODEGEN_SERIALIZER = |
36 structure CodegenSerializer: CODEGEN_SERIALIZER = |
91 gen_brackify (eval_fxy BR fxy_ctxt) (Pretty.breaks ps); |
86 gen_brackify (eval_fxy BR fxy_ctxt) (Pretty.breaks ps); |
92 |
87 |
93 fun brackify_infix infx fxy_ctxt ps = |
88 fun brackify_infix infx fxy_ctxt ps = |
94 gen_brackify (eval_fxy (INFX infx) fxy_ctxt) (Pretty.breaks ps); |
89 gen_brackify (eval_fxy (INFX infx) fxy_ctxt) (Pretty.breaks ps); |
95 |
90 |
|
91 type class_syntax = string * (string -> string option); |
|
92 type typ_syntax = int * ((fixity -> itype -> Pretty.T) |
|
93 -> fixity -> itype list -> Pretty.T); |
|
94 type term_syntax = int * ((CodegenNames.var_ctxt -> fixity -> iterm -> Pretty.T) |
|
95 -> CodegenNames.var_ctxt -> fixity -> (iterm * itype) list -> Pretty.T); |
|
96 |
96 |
97 |
97 (* user-defined syntax *) |
98 (* user-defined syntax *) |
98 |
99 |
99 datatype 'a mixfix = |
100 datatype 'a mixfix = |
100 Arg of fixity |
101 Arg of fixity |
101 | Pretty of Pretty.T; |
102 | Pretty of Pretty.T; |
102 |
103 |
103 fun mk_mixfix (fixity_this, mfx) = |
104 fun mk_mixfix prep_arg (fixity_this, mfx) = |
104 let |
105 let |
105 fun is_arg (Arg _) = true |
106 fun is_arg (Arg _) = true |
106 | is_arg _ = false; |
107 | is_arg _ = false; |
107 val i = (length o filter is_arg) mfx; |
108 val i = (length o filter is_arg) mfx; |
108 fun fillin _ [] [] = |
109 fun fillin _ [] [] = |
109 [] |
110 [] |
110 | fillin pr (Arg fxy :: mfx) (a :: args) = |
111 | fillin pr (Arg fxy :: mfx) (a :: args) = |
111 pr fxy a :: fillin pr mfx args |
112 (pr fxy o prep_arg) a :: fillin pr mfx args |
112 | fillin pr (Pretty p :: mfx) args = |
113 | fillin pr (Pretty p :: mfx) args = |
113 p :: fillin pr mfx args |
114 p :: fillin pr mfx args |
114 | fillin _ [] _ = |
115 | fillin _ [] _ = |
115 error ("Inconsistent mixfix: too many arguments") |
116 error ("Inconsistent mixfix: too many arguments") |
116 | fillin _ _ [] = |
117 | fillin _ _ [] = |
118 in |
119 in |
119 (i, fn pr => fn fixity_ctxt => fn args => |
120 (i, fn pr => fn fixity_ctxt => fn args => |
120 gen_brackify (eval_fxy fixity_this fixity_ctxt) (fillin pr mfx args)) |
121 gen_brackify (eval_fxy fixity_this fixity_ctxt) (fillin pr mfx args)) |
121 end; |
122 end; |
122 |
123 |
123 fun parse_infix (x, i) s = |
124 fun parse_infix prep_arg (x, i) s = |
124 let |
125 let |
125 val l = case x of L => INFX (i, L) | _ => INFX (i, X); |
126 val l = case x of L => INFX (i, L) | _ => INFX (i, X); |
126 val r = case x of R => INFX (i, R) | _ => INFX (i, X); |
127 val r = case x of R => INFX (i, R) | _ => INFX (i, X); |
127 in |
128 in |
128 mk_mixfix (INFX (i, x), [Arg l, (Pretty o Pretty.brk) 1, (Pretty o str) s, (Pretty o Pretty.brk) 1, Arg r]) |
129 mk_mixfix prep_arg (INFX (i, x), [Arg l, (Pretty o Pretty.brk) 1, (Pretty o str) s, (Pretty o Pretty.brk) 1, Arg r]) |
129 end; |
130 end; |
130 |
131 |
131 fun parse_mixfix s = |
132 fun parse_mixfix prep_arg s = |
132 let |
133 let |
133 val sym_any = Scan.one Symbol.not_eof; |
134 val sym_any = Scan.one Symbol.not_eof; |
134 val parse = Scan.optional ($$ "!" >> K true) false -- Scan.repeat ( |
135 val parse = Scan.optional ($$ "!" >> K true) false -- Scan.repeat ( |
135 ($$ "(" -- $$ "_" -- $$ ")" >> K (Arg NOBR)) |
136 ($$ "(" -- $$ "_" -- $$ ")" >> K (Arg NOBR)) |
136 || ($$ "_" >> K (Arg BR)) |
137 || ($$ "_" >> K (Arg BR)) |
138 || (Scan.repeat1 |
139 || (Scan.repeat1 |
139 ( $$ "'" |-- sym_any |
140 ( $$ "'" |-- sym_any |
140 || Scan.unless ($$ "_" || $$ "/" || $$ "(" |-- $$ "_" |-- $$ ")") |
141 || Scan.unless ($$ "_" || $$ "/" || $$ "(" |-- $$ "_" |-- $$ ")") |
141 sym_any) >> (Pretty o str o implode))); |
142 sym_any) >> (Pretty o str o implode))); |
142 in case Scan.finite Symbol.stopper parse (Symbol.explode s) |
143 in case Scan.finite Symbol.stopper parse (Symbol.explode s) |
143 of ((_, p as [_]), []) => mk_mixfix (NOBR, p) |
144 of ((_, p as [_]), []) => mk_mixfix prep_arg (NOBR, p) |
144 | ((b, p as _ :: _ :: _), []) => mk_mixfix (if b then NOBR else BR, p) |
145 | ((b, p as _ :: _ :: _), []) => mk_mixfix prep_arg (if b then NOBR else BR, p) |
145 | _ => Scan.!! (the_default ("malformed mixfix annotation: " ^ quote s) o snd) Scan.fail () |
146 | _ => Scan.!! (the_default ("malformed mixfix annotation: " ^ quote s) o snd) Scan.fail () |
146 end; |
147 end; |
147 |
148 |
148 fun parse_args f args = |
149 fun parse_args f args = |
149 case Scan.read Args.stopper f args |
150 case Scan.read Args.stopper f args |
151 | NONE => error "Bad serializer arguments"; |
152 | NONE => error "Bad serializer arguments"; |
152 |
153 |
153 |
154 |
154 (* generic serializer combinators *) |
155 (* generic serializer combinators *) |
155 |
156 |
156 fun gen_pr_app pr_app' pr_term const_syntax vars fxy (app as ((c, (_, ty)), ts)) = |
157 fun gen_pr_app pr_app' pr_term const_syntax vars fxy (app as ((c, (_, tys)), ts)) = |
157 case const_syntax c |
158 case const_syntax c |
158 of NONE => brackify fxy (pr_app' vars app) |
159 of NONE => brackify fxy (pr_app' vars app) |
159 | SOME (i, pr) => |
160 | SOME (i, pr) => |
160 let |
161 let |
161 val k = if i < 0 then (length o fst o CodegenThingol.unfold_fun) ty else i |
162 val k = if i < 0 then length tys else i; |
|
163 fun pr' fxy ts = pr pr_term vars fxy (ts ~~ curry Library.take k tys); |
162 in if k = length ts |
164 in if k = length ts |
163 then |
165 then pr' fxy ts |
164 pr pr_term vars fxy ts |
166 else if k < length ts |
165 else if k < length ts |
167 then case chop k ts of (ts1, ts2) => brackify fxy (pr' APP ts1 :: map (pr_term vars BR) ts2) |
166 then case chop k ts of (ts1, ts2) => |
|
167 brackify fxy (pr pr_term vars APP ts1 :: map (pr_term vars BR) ts2) |
|
168 else pr_term vars fxy (CodegenThingol.eta_expand app k) |
168 else pr_term vars fxy (CodegenThingol.eta_expand app k) |
169 end; |
169 end; |
170 |
170 |
171 fun gen_pr_bind pr_bind' pr_term fxy ((v, pat), ty) vars = |
171 fun gen_pr_bind pr_bind' pr_term fxy ((v, pat), ty) vars = |
172 let |
172 let |
215 | NONE => NONE; |
215 | NONE => NONE; |
216 in CodegenThingol.unfoldr dest_monad t end; |
216 in CodegenThingol.unfoldr dest_monad t end; |
217 |
217 |
218 fun pretty_ml_string c_nil c_cons mk_char mk_string target_implode = |
218 fun pretty_ml_string c_nil c_cons mk_char mk_string target_implode = |
219 let |
219 let |
220 fun pretty pr vars fxy [t] = |
220 fun pretty pr vars fxy [(t, _)] = |
221 case implode_list c_nil c_cons t |
221 case implode_list c_nil c_cons t |
222 of SOME ts => (case implode_string mk_char mk_string ts |
222 of SOME ts => (case implode_string mk_char mk_string ts |
223 of SOME p => p |
223 of SOME p => p |
224 | NONE => Pretty.block [str target_implode, Pretty.brk 1, pr vars BR t]) |
224 | NONE => Pretty.block [str target_implode, Pretty.brk 1, pr vars BR t]) |
225 | NONE => Pretty.block [str target_implode, Pretty.brk 1, pr vars BR t] |
225 | NONE => Pretty.block [str target_implode, Pretty.brk 1, pr vars BR t] |
231 brackify_infix (target_fxy, R) fxy [ |
231 brackify_infix (target_fxy, R) fxy [ |
232 pr (INFX (target_fxy, X)) t1, |
232 pr (INFX (target_fxy, X)) t1, |
233 str target_cons, |
233 str target_cons, |
234 pr (INFX (target_fxy, R)) t2 |
234 pr (INFX (target_fxy, R)) t2 |
235 ]; |
235 ]; |
236 fun pretty pr vars fxy [t1, t2] = |
236 fun pretty pr vars fxy [(t1, _), (t2, _)] = |
237 case Option.map (cons t1) (implode_list c_nil c_cons t2) |
237 case Option.map (cons t1) (implode_list c_nil c_cons t2) |
238 of SOME ts => |
238 of SOME ts => |
239 (case mk_char_string |
239 (case mk_char_string |
240 of SOME (mk_char, mk_string) => |
240 of SOME (mk_char, mk_string) => |
241 (case implode_string mk_char mk_string ts |
241 (case implode_string mk_char mk_string ts |
245 | NONE => default (pr vars) fxy t1 t2; |
245 | NONE => default (pr vars) fxy t1 t2; |
246 in (2, pretty) end; |
246 in (2, pretty) end; |
247 |
247 |
248 val pretty_imperative_monad_bind = |
248 val pretty_imperative_monad_bind = |
249 let |
249 let |
250 fun pretty (pr : CodegenNames.var_ctxt -> fixity -> iterm -> Pretty.T) vars fxy [t1, (v, ty) `|-> t2] = |
250 fun pretty (pr : CodegenNames.var_ctxt -> fixity -> iterm -> Pretty.T) |
251 pr vars fxy (ICase ((t1, ty), ([(IVar v, t2)]))) |
251 vars fxy [(t1, _), ((v, ty) `|-> t2, _)] = |
252 | pretty pr vars fxy [t1, t2] = |
252 pr vars fxy (ICase ((t1, ty), ([(IVar v, t2)]))) |
|
253 | pretty pr vars fxy [(t1, _), (t2, ty2)] = |
253 let |
254 let |
254 (*this code suffers from the lack of a proper concept for bindings*) |
255 (*this code suffers from the lack of a proper concept for bindings*) |
255 val vs = CodegenThingol.fold_varnames cons t2 []; |
256 val vs = CodegenThingol.fold_varnames cons t2 []; |
256 val v = Name.variant vs "x"; |
257 val v = Name.variant vs "x"; |
257 val vars' = CodegenNames.intro_vars [v] vars; |
258 val vars' = CodegenNames.intro_vars [v] vars; |
258 val var = IVar v; |
259 val var = IVar v; |
259 val ty = "" `%% []; (*an approximation*) |
260 val ty = (hd o fst o CodegenThingol.unfold_fun) ty2; |
260 in pr vars' fxy (ICase ((t1, ty), ([(var, t2 `$ var)]))) end; |
261 in pr vars' fxy (ICase ((t1, ty), ([(var, t2 `$ var)]))) end; |
261 in (2, pretty) end; |
262 in (2, pretty) end; |
262 |
263 |
263 |
264 |
264 |
265 |
299 | MLClass of string * ((class * string) list * (vname * (string * itype) list)) |
300 | MLClass of string * ((class * string) list * (vname * (string * itype) list)) |
300 | MLClassinst of string * ((class * (string * (vname * sort) list)) |
301 | MLClassinst of string * ((class * (string * (vname * sort) list)) |
301 * ((class * (string * (string * dict list list))) list |
302 * ((class * (string * (string * dict list list))) list |
302 * (string * iterm) list)); |
303 * (string * iterm) list)); |
303 |
304 |
304 fun pr_sml tyco_syntax const_syntax keyword_vars deresolv is_cons ml_def = |
305 fun pr_sml tyco_syntax const_syntax labelled_name keyword_vars deresolv is_cons ml_def = |
305 let |
306 let |
306 val pr_label = translate_string (fn "." => "__" | c => c) o NameSpace.qualifier; |
307 val pr_label = translate_string (fn "." => "__" | c => c) o NameSpace.qualifier; |
307 fun pr_dicts fxy ds = |
308 fun pr_dicts fxy ds = |
308 let |
309 let |
309 fun pr_dictvar (v, (_, 1)) = first_upper v ^ "_" |
310 fun pr_dictvar (v, (_, 1)) = first_upper v ^ "_" |
401 :: pr_term vars NOBR td |
402 :: pr_term vars NOBR td |
402 :: pr "of" b |
403 :: pr "of" b |
403 :: map (pr "|") bs |
404 :: map (pr "|") bs |
404 ) |
405 ) |
405 end |
406 end |
406 and pr_app' vars (app as ((c, (iss, ty)), ts)) = |
407 and pr_app' vars (app as ((c, (iss, tys)), ts)) = |
407 if is_cons c then let |
408 if is_cons c then let |
408 val k = (length o fst o CodegenThingol.unfold_fun) ty |
409 val k = length tys |
409 in if k < 2 then |
410 in if k < 2 then |
410 (str o deresolv) c :: map (pr_term vars BR) ts |
411 (str o deresolv) c :: map (pr_term vars BR) ts |
411 else if k = length ts then |
412 else if k = length ts then |
412 [(str o deresolv) c, Pretty.enum "," "(" ")" (map (pr_term vars NOBR) ts)] |
413 [(str o deresolv) c, Pretty.enum "," "(" ")" (map (pr_term vars NOBR) ts)] |
413 else [pr_term vars BR (CodegenThingol.eta_expand app k)] end else |
414 else [pr_term vars BR (CodegenThingol.eta_expand app k)] end else |
427 | mk (_::_) _ = "fun" |
428 | mk (_::_) _ = "fun" |
428 | mk [] vs = if (null o filter_out (null o snd)) vs then "val" else "fun"; |
429 | mk [] vs = if (null o filter_out (null o snd)) vs then "val" else "fun"; |
429 fun chk (_, ((ts, _) :: _, (vs, _))) NONE = SOME (mk ts vs) |
430 fun chk (_, ((ts, _) :: _, (vs, _))) NONE = SOME (mk ts vs) |
430 | chk (_, ((ts, _) :: _, (vs, _))) (SOME defi) = |
431 | chk (_, ((ts, _) :: _, (vs, _))) (SOME defi) = |
431 if defi = mk ts vs then SOME defi |
432 if defi = mk ts vs then SOME defi |
432 else error ("Mixing simultaneous vals and funs not implemented"); |
433 else error ("Mixing simultaneous vals and funs not implemented: " |
|
434 ^ commas (map (labelled_name o fst) funns)); |
433 in the (fold chk funns NONE) end; |
435 in the (fold chk funns NONE) end; |
434 fun pr_funn definer (name, (eqs as eq::eqs', (raw_vs, ty))) = |
436 fun pr_funn definer (name, (eqs as eq::eqs', (raw_vs, ty))) = |
435 let |
437 let |
436 val vs = filter_out (null o snd) raw_vs; |
438 val vs = filter_out (null o snd) raw_vs; |
437 val shift = if null eqs' then I else |
439 val shift = if null eqs' then I else |
662 :: pr_term vars NOBR td |
664 :: pr_term vars NOBR td |
663 :: pr "with" b |
665 :: pr "with" b |
664 :: map (pr "|") bs |
666 :: map (pr "|") bs |
665 ) |
667 ) |
666 end |
668 end |
667 and pr_app' vars (app as ((c, (iss, ty)), ts)) = |
669 and pr_app' vars (app as ((c, (iss, tys)), ts)) = |
668 if is_cons c then |
670 if is_cons c then |
669 if (length o fst o CodegenThingol.unfold_fun) ty = length ts |
671 if length tys = length ts |
670 then case ts |
672 then case ts |
671 of [] => [(str o deresolv) c] |
673 of [] => [(str o deresolv) c] |
672 | [t] => [(str o deresolv) c, pr_term vars BR t] |
674 | [t] => [(str o deresolv) c, pr_term vars BR t] |
673 | _ => [(str o deresolv) c, Pretty.enum "," "(" ")" (map (pr_term vars NOBR) ts)] |
675 | _ => [(str o deresolv) c, Pretty.enum "," "(" ")" (map (pr_term vars NOBR) ts)] |
674 else [pr_term vars BR (CodegenThingol.eta_expand app ((length o fst o CodegenThingol.unfold_fun) ty))] |
676 else [pr_term vars BR (CodegenThingol.eta_expand app (length tys))] |
675 else (str o deresolv) c |
677 else (str o deresolv) c |
676 :: ((map (pr_dicts BR) o filter_out null) iss @ map (pr_term vars BR) ts) |
678 :: ((map (pr_dicts BR) o filter_out null) iss @ map (pr_term vars BR) ts) |
677 and pr_app vars = gen_pr_app pr_app' pr_term const_syntax vars |
679 and pr_app vars = gen_pr_app pr_app' pr_term const_syntax vars |
678 and pr_bind' ((NONE, NONE), _) = str "_" |
680 and pr_bind' ((NONE, NONE), _) = str "_" |
679 | pr_bind' ((SOME v, NONE), _) = str v |
681 | pr_bind' ((SOME v, NONE), _) = str v |
915 in (x, (nsp_fun, nsp_typ')) end; |
917 in (x, (nsp_fun, nsp_typ')) end; |
916 fun mk_funs defs = |
918 fun mk_funs defs = |
917 fold_map |
919 fold_map |
918 (fn (name, CodegenThingol.Fun info) => |
920 (fn (name, CodegenThingol.Fun info) => |
919 map_nsp_fun (name_def false name) >> (fn base => (base, (name, info))) |
921 map_nsp_fun (name_def false name) >> (fn base => (base, (name, info))) |
920 | (name, def) => error ("Function block containing illegal def: " ^ quote name) |
922 | (name, def) => error ("Function block containing illegal definition: " ^ labelled_name name) |
921 ) defs |
923 ) defs |
922 >> (split_list #> apsnd MLFuns); |
924 >> (split_list #> apsnd MLFuns); |
923 fun mk_datatype defs = |
925 fun mk_datatype defs = |
924 fold_map |
926 fold_map |
925 (fn (name, CodegenThingol.Datatype info) => |
927 (fn (name, CodegenThingol.Datatype info) => |
926 map_nsp_typ (name_def false name) >> (fn base => (base, SOME (name, info))) |
928 map_nsp_typ (name_def false name) >> (fn base => (base, SOME (name, info))) |
927 | (name, CodegenThingol.Datatypecons _) => |
929 | (name, CodegenThingol.Datatypecons _) => |
928 map_nsp_fun (name_def true name) >> (fn base => (base, NONE)) |
930 map_nsp_fun (name_def true name) >> (fn base => (base, NONE)) |
929 | (name, def) => error ("Datatype block containing illegal def: " ^ quote name) |
931 | (name, def) => error ("Datatype block containing illegal definition: " ^ labelled_name name) |
930 ) defs |
932 ) defs |
931 >> (split_list #> apsnd (map_filter I |
933 >> (split_list #> apsnd (map_filter I |
932 #> (fn [] => error ("Datatype block without data: " ^ (commas o map (quote o fst)) defs) |
934 #> (fn [] => error ("Datatype block without data definition: " ^ (commas o map (labelled_name o fst)) defs) |
933 | infos => MLDatas infos))); |
935 | infos => MLDatas infos))); |
934 fun mk_class defs = |
936 fun mk_class defs = |
935 fold_map |
937 fold_map |
936 (fn (name, CodegenThingol.Class info) => |
938 (fn (name, CodegenThingol.Class info) => |
937 map_nsp_typ (name_def false name) >> (fn base => (base, SOME (name, info))) |
939 map_nsp_typ (name_def false name) >> (fn base => (base, SOME (name, info))) |
938 | (name, CodegenThingol.Classrel _) => |
940 | (name, CodegenThingol.Classrel _) => |
939 map_nsp_fun (name_def false name) >> (fn base => (base, NONE)) |
941 map_nsp_fun (name_def false name) >> (fn base => (base, NONE)) |
940 | (name, CodegenThingol.Classop _) => |
942 | (name, CodegenThingol.Classop _) => |
941 map_nsp_fun (name_def false name) >> (fn base => (base, NONE)) |
943 map_nsp_fun (name_def false name) >> (fn base => (base, NONE)) |
942 | (name, def) => error ("Class block containing illegal def: " ^ quote name) |
944 | (name, def) => error ("Class block containing illegal definition: " ^ labelled_name name) |
943 ) defs |
945 ) defs |
944 >> (split_list #> apsnd (map_filter I |
946 >> (split_list #> apsnd (map_filter I |
945 #> (fn [] => error ("Class block without class: " ^ (commas o map (quote o fst)) defs) |
947 #> (fn [] => error ("Class block without class definition: " ^ (commas o map (labelled_name o fst)) defs) |
946 | [info] => MLClass info))); |
948 | [info] => MLClass info))); |
947 fun mk_inst [(name, CodegenThingol.Classinst info)] = |
949 fun mk_inst [(name, CodegenThingol.Classinst info)] = |
948 map_nsp_fun (name_def false name) |
950 map_nsp_fun (name_def false name) |
949 >> (fn base => ([base], MLClassinst (name, info))); |
951 >> (fn base => ([base], MLClassinst (name, info))); |
950 fun add_group mk defs nsp_nodes = |
952 fun add_group mk defs nsp_nodes = |
955 |> fold (fold (insert (op =)) o Graph.imm_succs code) names |
957 |> fold (fold (insert (op =)) o Graph.imm_succs code) names |
956 |> subtract (op =) names; |
958 |> subtract (op =) names; |
957 val (modls, _) = (split_list o map dest_name) names; |
959 val (modls, _) = (split_list o map dest_name) names; |
958 val modl = (the_single o distinct (op =)) modls |
960 val modl = (the_single o distinct (op =)) modls |
959 handle Empty => |
961 handle Empty => |
960 error ("Illegal mutual dependencies: " ^ commas names); |
962 error ("Illegal mutual dependencies: " ^ commas (map labelled_name names)); |
961 val modl' = name_modl modl; |
963 val modl' = name_modl modl; |
962 val modl_explode = NameSpace.explode modl'; |
964 val modl_explode = NameSpace.explode modl'; |
963 fun add_dep name name'' = |
965 fun add_dep name name'' = |
964 let |
966 let |
965 val modl'' = (name_modl o fst o dest_name) name''; |
967 val modl'' = (name_modl o fst o dest_name) name''; |
998 add_group mk_class defs |
1000 add_group mk_class defs |
999 | group_defs ((defs as (_, CodegenThingol.Classop _)::_)) = |
1001 | group_defs ((defs as (_, CodegenThingol.Classop _)::_)) = |
1000 add_group mk_class defs |
1002 add_group mk_class defs |
1001 | group_defs ((defs as [(_, CodegenThingol.Classinst _)])) = |
1003 | group_defs ((defs as [(_, CodegenThingol.Classinst _)])) = |
1002 add_group mk_inst defs |
1004 add_group mk_inst defs |
1003 | group_defs defs = error ("Illegal mutual dependencies: " ^ (commas o map fst) defs) |
1005 | group_defs defs = error ("Illegal mutual dependencies: " ^ (commas o map (labelled_name o fst)) defs) |
1004 val (_, nodes) = |
1006 val (_, nodes) = |
1005 empty_module |
1007 empty_module |
1006 |> fold group_defs (map (AList.make (Graph.get_node code)) |
1008 |> fold group_defs (map (AList.make (Graph.get_node code)) |
1007 (rev (Graph.strong_conn code))) |
1009 (rev (Graph.strong_conn code))) |
1008 fun deresolver prefix name = |
1010 fun deresolver prefix name = |
1016 of Module (_, (_, g)) => g) modl' |
1018 of Module (_, (_, g)) => g) modl' |
1017 |> (fn g => case Graph.get_node g name of Def (defname, _) => defname); |
1019 |> (fn g => case Graph.get_node g name of Def (defname, _) => defname); |
1018 in |
1020 in |
1019 NameSpace.implode (remainder @ [defname']) |
1021 NameSpace.implode (remainder @ [defname']) |
1020 end handle Graph.UNDEF _ => |
1022 end handle Graph.UNDEF _ => |
1021 error "Unknown name: " ^ quote name; |
1023 error ("Unknown definition name: " ^ labelled_name name); |
1022 fun the_prolog modlname = case module_prolog modlname |
1024 fun the_prolog modlname = case module_prolog modlname |
1023 of NONE => [] |
1025 of NONE => [] |
1024 | SOME p => [p, str ""]; |
1026 | SOME p => [p, str ""]; |
1025 fun pr_node prefix (Def (_, NONE)) = |
1027 fun pr_node prefix (Def (_, NONE)) = |
1026 NONE |
1028 NONE |
1027 | pr_node prefix (Def (_, SOME def)) = |
1029 | pr_node prefix (Def (_, SOME def)) = |
1028 SOME (pr_def tyco_syntax const_syntax init_vars (deresolver prefix) is_cons def) |
1030 SOME (pr_def tyco_syntax const_syntax labelled_name init_vars (deresolver prefix) is_cons def) |
1029 | pr_node prefix (Module (dmodlname, (_, nodes))) = |
1031 | pr_node prefix (Module (dmodlname, (_, nodes))) = |
1030 SOME (pr_modl dmodlname (the_prolog (NameSpace.implode (prefix @ [dmodlname])) |
1032 SOME (pr_modl dmodlname (the_prolog (NameSpace.implode (prefix @ [dmodlname])) |
1031 @ separate (str "") ((map_filter (pr_node (prefix @ [dmodlname]) o Graph.get_node nodes) |
1033 @ separate (str "") ((map_filter (pr_node (prefix @ [dmodlname]) o Graph.get_node nodes) |
1032 o rev o flat o Graph.strong_conn) nodes))); |
1034 o rev o flat o Graph.strong_conn) nodes))); |
1033 val p = pr_modl "ROOT" (the_prolog "" @ separate (str "") ((map_filter |
1035 val p = pr_modl "ROOT" (the_prolog "" @ separate (str "") ((map_filter |
1308 "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr", |
1310 "hiding", "deriving", "where", "case", "of", "infix", "infixl", "infixr", |
1309 "import", "default", "forall", "let", "in", "class", "qualified", "data", |
1311 "import", "default", "forall", "let", "in", "class", "qualified", "data", |
1310 "newtype", "instance", "if", "then", "else", "type", "as", "do", "module" |
1312 "newtype", "instance", "if", "then", "else", "type", "as", "do", "module" |
1311 ]; |
1313 ]; |
1312 |
1314 |
1313 fun seri_haskell module_prefix destination string_classes reserved_user module_alias module_prolog |
1315 fun seri_haskell module_prefix destination string_classes labelled_name reserved_user module_alias module_prolog |
1314 class_syntax tyco_syntax const_syntax code = |
1316 class_syntax tyco_syntax const_syntax code = |
1315 let |
1317 let |
1316 val _ = Option.map File.check destination; |
1318 val _ = Option.map File.check destination; |
1317 val empty_names = Name.make_context (reserved_haskell @ reserved_user); |
1319 val empty_names = Name.make_context (reserved_haskell @ reserved_user); |
1318 val name_modl = mk_modl_name_tab empty_names module_prefix module_alias code |
1320 val name_modl = mk_modl_name_tab empty_names module_prefix module_alias code |
1319 fun add_def (name, (def, deps : string list)) = |
1321 fun add_def (name, (def, deps)) = |
1320 let |
1322 let |
1321 val (modl, base) = dest_name name; |
1323 val (modl, base) = dest_name name; |
1322 fun name_def base = Name.variants [base] #>> the_single; |
1324 fun name_def base = Name.variants [base] #>> the_single; |
1323 fun add_fun upper (nsp_fun, nsp_typ) = |
1325 fun add_fun upper (nsp_fun, nsp_typ) = |
1324 let |
1326 let |
1361 (Graph.strong_conn code |> flat)) Symtab.empty; |
1363 (Graph.strong_conn code |> flat)) Symtab.empty; |
1362 val init_vars = CodegenNames.make_vars (reserved_haskell @ reserved_user); |
1364 val init_vars = CodegenNames.make_vars (reserved_haskell @ reserved_user); |
1363 fun deresolv name = |
1365 fun deresolv name = |
1364 (fst o fst o the o AList.lookup (op =) ((fst o snd o the |
1366 (fst o fst o the o AList.lookup (op =) ((fst o snd o the |
1365 o Symtab.lookup code') ((name_modl o fst o dest_name) name))) name |
1367 o Symtab.lookup code') ((name_modl o fst o dest_name) name))) name |
1366 handle Option => "(error \"undefined name " ^ name ^ "\")"; |
1368 handle Option => error ("Unknown definition name: " ^ labelled_name name); |
1367 fun deresolv_here name = |
1369 fun deresolv_here name = |
1368 (snd o fst o the o AList.lookup (op =) ((fst o snd o the |
1370 (snd o fst o the o AList.lookup (op =) ((fst o snd o the |
1369 o Symtab.lookup code') ((name_modl o fst o dest_name) name))) name |
1371 o Symtab.lookup code') ((name_modl o fst o dest_name) name))) name |
1370 handle Option => "(error \"undefined name " ^ name ^ "\")"; |
1372 handle Option => error ("Unknown definition name: " ^ labelled_name name); |
1371 fun deriving_show tyco = |
1373 fun deriving_show tyco = |
1372 let |
1374 let |
1373 fun deriv _ "fun" = false |
1375 fun deriv _ "fun" = false |
1374 | deriv tycos tyco = member (op =) tycos tyco orelse |
1376 | deriv tycos tyco = member (op =) tycos tyco orelse |
1375 case the_default CodegenThingol.Bot (try (Graph.get_node code) tyco) |
1377 case the_default CodegenThingol.Bot (try (Graph.get_node code) tyco) |
1378 (maps snd cs) |
1380 (maps snd cs) |
1379 and deriv' tycos (tyco `%% tys) = deriv tycos tyco |
1381 and deriv' tycos (tyco `%% tys) = deriv tycos tyco |
1380 andalso forall (deriv' tycos) tys |
1382 andalso forall (deriv' tycos) tys |
1381 | deriv' _ (ITyVar _) = true |
1383 | deriv' _ (ITyVar _) = true |
1382 in deriv [] tyco end; |
1384 in deriv [] tyco end; |
1383 fun seri_def qualified = pr_haskell class_syntax tyco_syntax const_syntax init_vars |
1385 fun seri_def qualified = pr_haskell class_syntax tyco_syntax const_syntax labelled_name init_vars |
1384 deresolv_here (if qualified then deresolv else deresolv_here) (if string_classes then deriving_show else K false); |
1386 deresolv_here (if qualified then deresolv else deresolv_here) |
|
1387 (if string_classes then deriving_show else K false); |
1385 fun write_module (SOME destination) modlname = |
1388 fun write_module (SOME destination) modlname = |
1386 let |
1389 let |
1387 val filename = case modlname |
1390 val filename = case modlname |
1388 of "" => Path.explode "Main.hs" |
1391 of "" => Path.explode "Main.hs" |
1389 | _ => (Path.ext "hs" o Path.explode o implode o separate "/" o NameSpace.explode) modlname; |
1392 | _ => (Path.ext "hs" o Path.explode o implode o separate "/" o NameSpace.explode) modlname; |
1487 Symtab.merge (op =) (alias1, alias2), |
1490 Symtab.merge (op =) (alias1, alias2), |
1488 Symtab.merge (op =) (prolog1, prolog2) |
1491 Symtab.merge (op =) (prolog1, prolog2) |
1489 ); |
1492 ); |
1490 |
1493 |
1491 type serializer = Args.T list |
1494 type serializer = Args.T list |
|
1495 -> (string -> string) |
1492 -> string list |
1496 -> string list |
1493 -> (string -> string option) |
1497 -> (string -> string option) |
1494 -> (string -> Pretty.T option) |
1498 -> (string -> Pretty.T option) |
1495 -> (string -> (string * (string -> string option)) option) |
1499 -> (string -> class_syntax option) |
1496 -> (string -> typ_syntax option) |
1500 -> (string -> typ_syntax option) |
1497 -> (string -> term_syntax option) |
1501 -> (string -> term_syntax option) |
1498 -> CodegenThingol.code -> unit; |
1502 -> CodegenThingol.code -> unit; |
1499 |
1503 |
1500 datatype target = Target of { |
1504 datatype target = Target of { |
1572 #> add_serializer (target_OCaml, isar_seri_ocaml) |
1576 #> add_serializer (target_OCaml, isar_seri_ocaml) |
1573 #> add_serializer (target_Haskell, isar_seri_haskell) |
1577 #> add_serializer (target_Haskell, isar_seri_haskell) |
1574 #> add_serializer (target_diag, (fn _ => fn _ => seri_diagnosis)) |
1578 #> add_serializer (target_diag, (fn _ => fn _ => seri_diagnosis)) |
1575 ); |
1579 ); |
1576 |
1580 |
1577 fun get_serializer thy target args = fn cs => |
1581 fun get_serializer thy target args labelled_name = fn cs => |
1578 let |
1582 let |
1579 val data = case Symtab.lookup (CodegenSerializerData.get thy) target |
1583 val data = case Symtab.lookup (CodegenSerializerData.get thy) target |
1580 of SOME data => data |
1584 of SOME data => data |
1581 | NONE => error ("Unknown code target language: " ^ quote target); |
1585 | NONE => error ("Unknown code target language: " ^ quote target); |
1582 val seri = the_serializer data; |
1586 val seri = the_serializer data; |
1586 fun fun_of sys = (Option.map fst oo Symtab.lookup) sys; |
1590 fun fun_of sys = (Option.map fst oo Symtab.lookup) sys; |
1587 val project = if target = target_diag then I |
1591 val project = if target = target_diag then I |
1588 else CodegenThingol.project_code |
1592 else CodegenThingol.project_code |
1589 (Symtab.keys class @ Symtab.keys inst @ Symtab.keys tyco @ Symtab.keys const) cs; |
1593 (Symtab.keys class @ Symtab.keys inst @ Symtab.keys tyco @ Symtab.keys const) cs; |
1590 in |
1594 in |
1591 project #> seri args reserved (Symtab.lookup alias) (Symtab.lookup prolog) |
1595 project #> seri args (labelled_name thy) reserved (Symtab.lookup alias) (Symtab.lookup prolog) |
1592 (fun_of class) (fun_of tyco) (fun_of const) |
1596 (fun_of class) (fun_of tyco) (fun_of const) |
1593 end; |
1597 end; |
1594 |
1598 |
1595 val eval_verbose = ref false; |
1599 val eval_verbose = ref false; |
1596 |
1600 |
1597 fun eval_term thy code ((ref_name, reff), t) = |
1601 fun eval_term thy labelled_name code ((ref_name, reff), t) = |
1598 let |
1602 let |
1599 val val_name = "eval.EVAL.EVAL"; |
1603 val val_name = "eval.EVAL.EVAL"; |
1600 val val_name' = "ROOT.eval.EVAL"; |
1604 val val_name' = "ROOT.eval.EVAL"; |
1601 val data = (the o Symtab.lookup (CodegenSerializerData.get thy)) "SML" |
1605 val data = (the o Symtab.lookup (CodegenSerializerData.get thy)) "SML" |
1602 val reserved = the_reserved data; |
1606 val reserved = the_reserved data; |
1760 val pr = pretty_haskell_monad c_mbind'' c_kbind'' |
1764 val pr = pretty_haskell_monad c_mbind'' c_kbind'' |
1761 in |
1765 in |
1762 thy |
1766 thy |
1763 |> gen_add_syntax_const (K I) target_Haskell c_run' (SOME pr) |
1767 |> gen_add_syntax_const (K I) target_Haskell c_run' (SOME pr) |
1764 |> gen_add_syntax_const (K I) target_Haskell c_mbind' |
1768 |> gen_add_syntax_const (K I) target_Haskell c_mbind' |
1765 (no_bindings (SOME (parse_infix (L, 1) ">>="))) |
1769 (no_bindings (SOME (parse_infix fst (L, 1) ">>="))) |
1766 |> gen_add_syntax_const (K I) target_Haskell c_kbind' |
1770 |> gen_add_syntax_const (K I) target_Haskell c_kbind' |
1767 (no_bindings (SOME (parse_infix (L, 1) ">>"))) |
1771 (no_bindings (SOME (parse_infix fst (L, 1) ">>"))) |
1768 end; |
1772 end; |
1769 |
1773 |
1770 val add_syntax_class = gen_add_syntax_class read_class CodegenConsts.read_const; |
1774 val add_syntax_class = gen_add_syntax_class read_class CodegenConsts.read_const; |
1771 val add_syntax_inst = gen_add_syntax_inst read_class read_type; |
1775 val add_syntax_inst = gen_add_syntax_inst read_class read_type; |
1772 val add_syntax_tyco = gen_add_syntax_tyco read_type; |
1776 val add_syntax_tyco = gen_add_syntax_tyco read_type; |
1797 #-> (fn things => Scan.repeat1 (P.$$$ "(" |-- P.name -- |
1801 #-> (fn things => Scan.repeat1 (P.$$$ "(" |-- P.name -- |
1798 (zip_list things parse_syntax (P.$$$ "and")) --| P.$$$ ")")); |
1802 (zip_list things parse_syntax (P.$$$ "and")) --| P.$$$ ")")); |
1799 |
1803 |
1800 val (infixK, infixlK, infixrK) = ("infix", "infixl", "infixr"); |
1804 val (infixK, infixlK, infixrK) = ("infix", "infixl", "infixr"); |
1801 |
1805 |
1802 fun parse_syntax xs = |
1806 fun parse_syntax prep_arg xs = |
1803 Scan.option (( |
1807 Scan.option (( |
1804 ((P.$$$ infixK >> K X) |
1808 ((P.$$$ infixK >> K X) |
1805 || (P.$$$ infixlK >> K L) |
1809 || (P.$$$ infixlK >> K L) |
1806 || (P.$$$ infixrK >> K R)) |
1810 || (P.$$$ infixrK >> K R)) |
1807 -- P.nat >> parse_infix |
1811 -- P.nat >> parse_infix prep_arg |
1808 || Scan.succeed parse_mixfix) |
1812 || Scan.succeed (parse_mixfix prep_arg)) |
1809 -- P.string |
1813 -- P.string |
1810 >> (fn (parse, s) => parse s)) xs; |
1814 >> (fn (parse, s) => parse s)) xs; |
1811 |
1815 |
1812 val (code_classK, code_instanceK, code_typeK, code_constK, code_monadK, |
1816 val (code_classK, code_instanceK, code_typeK, code_constK, code_monadK, |
1813 code_reservedK, code_modulenameK, code_moduleprologK) = |
1817 code_reservedK, code_modulenameK, code_moduleprologK) = |
1874 fold (fn (raw_inst, add_del) => add_syntax_inst target raw_inst add_del) syns) |
1878 fold (fn (raw_inst, add_del) => add_syntax_inst target raw_inst add_del) syns) |
1875 ); |
1879 ); |
1876 |
1880 |
1877 val code_typeP = |
1881 val code_typeP = |
1878 OuterSyntax.command code_typeK "define code syntax for type constructor" K.thy_decl ( |
1882 OuterSyntax.command code_typeK "define code syntax for type constructor" K.thy_decl ( |
1879 parse_multi_syntax P.xname parse_syntax |
1883 parse_multi_syntax P.xname (parse_syntax I) |
1880 >> (Toplevel.theory oo fold) (fn (target, syns) => |
1884 >> (Toplevel.theory oo fold) (fn (target, syns) => |
1881 fold (fn (raw_tyco, syn) => add_syntax_tyco target raw_tyco syn) syns) |
1885 fold (fn (raw_tyco, syn) => add_syntax_tyco target raw_tyco syn) syns) |
1882 ); |
1886 ); |
1883 |
1887 |
1884 val code_constP = |
1888 val code_constP = |
1885 OuterSyntax.command code_constK "define code syntax for constant" K.thy_decl ( |
1889 OuterSyntax.command code_constK "define code syntax for constant" K.thy_decl ( |
1886 parse_multi_syntax P.term parse_syntax |
1890 parse_multi_syntax P.term (parse_syntax fst) |
1887 >> (Toplevel.theory oo fold) (fn (target, syns) => |
1891 >> (Toplevel.theory oo fold) (fn (target, syns) => |
1888 fold (fn (raw_const, syn) => add_syntax_const target raw_const (no_bindings syn)) syns) |
1892 fold (fn (raw_const, syn) => add_syntax_const target raw_const (no_bindings syn)) syns) |
1889 ); |
1893 ); |
1890 |
1894 |
1891 val code_monadP = |
1895 val code_monadP = |