| author | haftmann | 
| Wed, 15 Nov 2006 17:05:38 +0100 | |
| changeset 21379 | a0561695167a | 
| parent 21160 | 0fb5e2123f93 | 
| child 21838 | f9243336f54e | 
| permissions | -rw-r--r-- | 
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 1 | (* Title: Pure/Tools/codegen_thingol.ML | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 2 | ID: $Id$ | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 3 | Author: Florian Haftmann, TU Muenchen | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 4 | |
| 20855 | 5 | Intermediate language ("Thin-gol") representing extracted code.
 | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 6 | *) | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 7 | |
| 19167 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 8 | infix 8 `%%; | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 9 | infixr 6 `->; | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 10 | infixr 6 `-->; | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 11 | infix 4 `$; | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 12 | infix 4 `$$; | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 13 | infixr 3 `|->; | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 14 | infixr 3 `|-->; | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 15 | |
| 19136 | 16 | signature BASIC_CODEGEN_THINGOL = | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 17 | sig | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 18 | type vname = string; | 
| 20456 | 19 | datatype inst = | 
| 20 | Instance of string * inst list list | |
| 21 | | Context of class list * (vname * int); | |
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 22 | datatype itype = | 
| 19167 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 23 | `%% of string * itype list | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 24 | | ITyVar of vname; | 
| 20105 | 25 | datatype iterm = | 
| 20456 | 26 | IConst of string * (inst list list * itype) | 
| 19167 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 27 | | IVar of vname | 
| 20105 | 28 | | `$ of iterm * iterm | 
| 29 | | `|-> of (vname * itype) * iterm | |
| 21012 | 30 | | INum of IntInf.int | 
| 31 | | IChar of string (*length one!*) | |
| 32 | | ICase of (iterm * itype) * (iterm * iterm) list; | |
| 33 | (*(discriminendum term (td), discriminendum type (ty)), | |
| 34 | [(selector pattern (p), body term (t))] (bs))*) | |
| 21123 | 35 | val `-> : itype * itype -> itype; | 
| 20896 | 36 | val `--> : itype list * itype -> itype; | 
| 37 | val `$$ : iterm * iterm list -> iterm; | |
| 38 | val `|--> : (vname * itype) list * iterm -> iterm; | |
| 39 | type typscheme = (vname * sort) list * itype; | |
| 19136 | 40 | end; | 
| 41 | ||
| 42 | signature CODEGEN_THINGOL = | |
| 43 | sig | |
| 44 | include BASIC_CODEGEN_THINGOL; | |
| 18216 | 45 |   val unfoldl: ('a -> ('a * 'b) option) -> 'a -> 'a * 'b list;
 | 
| 46 |   val unfoldr: ('a -> ('b * 'a) option) -> 'a -> 'b list * 'a;
 | |
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 47 | val unfold_fun: itype -> itype list * itype; | 
| 20105 | 48 | val unfold_app: iterm -> iterm * iterm list; | 
| 21012 | 49 | val unfold_abs: iterm -> ((vname * iterm option) * itype) list * iterm; | 
| 20105 | 50 | val unfold_let: iterm -> ((iterm * itype) * iterm) list * iterm; | 
| 51 | val unfold_const_app: iterm -> | |
| 20456 | 52 | ((string * (inst list list * itype)) * iterm list) option; | 
| 53 | val eta_expand: (string * (inst list list * itype)) * iterm list -> int -> iterm; | |
| 20896 | 54 | val fold_constnames: (string -> 'a -> 'a) -> iterm -> 'a -> 'a; | 
| 55 | val fold_varnames: (string -> 'a -> 'a) -> iterm -> 'a -> 'a; | |
| 56 | val fold_unbound_varnames: (string -> 'a -> 'a) -> iterm -> 'a -> 'a; | |
| 18170 | 57 | |
| 58 | datatype def = | |
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 59 | Bot | 
| 20456 | 60 | | Fun of (iterm list * iterm) list * typscheme | 
| 61 | | Datatype of (vname * sort) list * (string * itype list) list | |
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 62 | | Datatypecons of string | 
| 20456 | 63 | | Class of class list * (vname * (string * itype) list) | 
| 21082 | 64 | | Classop of class | 
| 20389 | 65 | | Classinst of (class * (string * (vname * sort) list)) | 
| 20466 | 66 | * ((class * (string * inst list list)) list | 
| 20389 | 67 | * (string * iterm) list); | 
| 20896 | 68 | type code = def Graph.T; | 
| 18170 | 69 | type transact; | 
| 20896 | 70 | val empty_code: code; | 
| 71 | val get_def: code -> string -> def; | |
| 72 | val merge_code: code * code -> code; | |
| 21012 | 73 | val project_code: string list (*hidden*) -> string list option (*selected*) | 
| 74 | -> code -> code; | |
| 21160 | 75 | val add_eval_def: string (*bind name*) * iterm -> code -> code; | 
| 21012 | 76 | |
| 20896 | 77 | val ensure_def: (transact -> def * code) -> bool -> string | 
| 19884 | 78 | -> string -> transact -> transact; | 
| 20896 | 79 | val succeed: 'a -> transact -> 'a * code; | 
| 80 | val fail: string -> transact -> 'a * code; | |
| 19884 | 81 | val message: string -> (transact -> 'a) -> transact -> 'a; | 
| 20896 | 82 | val start_transact: string option -> (transact -> 'a * transact) -> code -> 'a * code; | 
| 18216 | 83 | |
| 21082 | 84 | type var_ctxt; | 
| 85 | val make_vars: string list -> var_ctxt; | |
| 86 | val intro_vars: string list -> var_ctxt -> var_ctxt; | |
| 87 | val lookup_var: var_ctxt -> string -> string; | |
| 88 | ||
| 20835 | 89 | val trace: bool ref; | 
| 90 |   val tracing: ('a -> string) -> 'a -> 'a;
 | |
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 91 | end; | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 92 | |
| 18850 | 93 | structure CodegenThingol: CODEGEN_THINGOL = | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 94 | struct | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 95 | |
| 18170 | 96 | (** auxiliary **) | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 97 | |
| 20835 | 98 | val trace = ref false; | 
| 99 | fun tracing f x = (if !trace then Output.tracing (f x) else (); x); | |
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 100 | |
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 101 | fun unfoldl dest x = | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 102 | case dest x | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 103 | of NONE => (x, []) | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 104 | | SOME (x1, x2) => | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 105 | let val (x', xs') = unfoldl dest x1 in (x', xs' @ [x2]) end; | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 106 | |
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 107 | fun unfoldr dest x = | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 108 | case dest x | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 109 | of NONE => ([], x) | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 110 | | SOME (x1, x2) => | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 111 | let val (xs', x') = unfoldr dest x2 in (x1::xs', x') end; | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 112 | |
| 18170 | 113 | |
| 114 | ||
| 115 | (** language core - types, pattern, expressions **) | |
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 116 | |
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 117 | (* language representation *) | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 118 | |
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 119 | type vname = string; | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 120 | |
| 20456 | 121 | datatype inst = | 
| 122 | Instance of string * inst list list | |
| 123 | | Context of class list * (vname * int); | |
| 18885 | 124 | |
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 125 | datatype itype = | 
| 19167 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 126 | `%% of string * itype list | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 127 | | ITyVar of vname; | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 128 | |
| 20105 | 129 | datatype iterm = | 
| 20456 | 130 | IConst of string * (inst list list * itype) | 
| 19167 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 131 | | IVar of vname | 
| 20105 | 132 | | `$ of iterm * iterm | 
| 133 | | `|-> of (vname * itype) * iterm | |
| 21012 | 134 | | INum of IntInf.int | 
| 135 | | IChar of string | |
| 136 | | ICase of (iterm * itype) * (iterm * iterm) list; | |
| 19167 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 137 | (*see also signature*) | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 138 | |
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 139 | (* | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 140 | variable naming conventions | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 141 | |
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 142 | bare names: | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 143 | variable names v | 
| 20439 | 144 | class names class | 
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 145 | type constructor names tyco | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 146 | datatype names dtco | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 147 | const names (general) c | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 148 | constructor names co | 
| 20439 | 149 | class operation names clsop (op) | 
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 150 | arbitrary name s | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 151 | |
| 20896 | 152 | v, c, co, clsop also annotated with types etc. | 
| 20439 | 153 | |
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 154 | constructs: | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 155 | sort sort | 
| 20456 | 156 | type parameters vs | 
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 157 | type ty | 
| 20456 | 158 | type schemes tysm | 
| 20439 | 159 | term t | 
| 160 | (term as pattern) p | |
| 161 | instance (classs, tyco) inst | |
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 162 | *) | 
| 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 163 | |
| 21123 | 164 | fun ty1 `-> ty2 = "fun" `%% [ty1, ty2]; | 
| 19167 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 165 | val op `--> = Library.foldr (op `->); | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 166 | val op `$$ = Library.foldl (op `$); | 
| 
f237c0cb3882
refined representation of codegen intermediate language
 haftmann parents: 
19150diff
changeset | 167 | val op `|--> = Library.foldr (op `|->); | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 168 | |
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 169 | val unfold_fun = unfoldr | 
| 21123 | 170 | (fn "fun" `%% [ty1, ty2] => SOME (ty1, ty2) | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 171 | | _ => NONE); | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 172 | |
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 173 | val unfold_app = unfoldl | 
| 20439 | 174 | (fn op `$ t => SOME t | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 175 | | _ => NONE); | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 176 | |
| 18282 | 177 | val unfold_abs = unfoldr | 
| 21012 | 178 | (fn (v, ty) `|-> (t as ICase ((IVar w, _), [(p, t')])) => | 
| 179 | if v = w then SOME (((v, SOME p), ty), t') else SOME (((v, NONE), ty), t) | |
| 180 | | (v, ty) `|-> t => SOME (((v, NONE), ty), t) | |
| 18282 | 181 | | _ => NONE) | 
| 182 | ||
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 183 | val unfold_let = unfoldr | 
| 21012 | 184 | (fn ICase ((td, ty), [(p, t)]) => SOME (((p, ty), td), t) | 
| 18169 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 185 | | _ => NONE); | 
| 
45def66f86cb
added modules for code generator generation two, not operational yet
 haftmann parents: diff
changeset | 186 | |
| 20439 | 187 | fun unfold_const_app t = | 
| 188 | case unfold_app t | |
| 189 | of (IConst c, ts) => SOME (c, ts) | |
| 18865 | 190 | | _ => NONE; | 
| 191 | ||
| 20896 | 192 | fun fold_aiterms f (t as IConst _) = | 
| 193 | f t | |
| 194 | | fold_aiterms f (t as IVar _) = | |
| 195 | f t | |
| 196 | | fold_aiterms f (t1 `$ t2) = | |
| 197 | fold_aiterms f t1 #> fold_aiterms f t2 | |
| 198 | | fold_aiterms f (t as _ `|-> t') = | |
| 199 | f t #> fold_aiterms f t' | |
| 21012 | 200 | | fold_aiterms f (t as INum _) = | 
| 201 | f t | |
| 202 | | fold_aiterms f (t as IChar _) = | |
| 203 | f t | |
| 204 | | fold_aiterms f (ICase ((td, _), bs)) = | |
| 205 | fold_aiterms f td #> fold (fn (p, t) => fold_aiterms f p #> fold_aiterms f t) bs; | |
| 19202 | 206 | |
| 20896 | 207 | fun fold_constnames f = | 
| 208 | let | |
| 209 | fun add (IConst (c, _)) = f c | |
| 210 | | add _ = I; | |
| 211 | in fold_aiterms add end; | |
| 18885 | 212 | |
| 20896 | 213 | fun fold_varnames f = | 
| 214 | let | |
| 215 | fun add (IVar v) = f v | |
| 216 | | add ((v, _) `|-> _) = f v | |
| 217 | | add _ = I; | |
| 218 | in fold_aiterms add end; | |
| 20709 | 219 | |
| 20896 | 220 | fun fold_unbound_varnames f = | 
| 18885 | 221 | let | 
| 20896 | 222 | fun add _ (IConst _) = | 
| 223 | I | |
| 224 | | add vs (IVar v) = | |
| 225 | if not (member (op =) vs v) then f v else I | |
| 226 | | add vs (t1 `$ t2) = | |
| 227 | add vs t1 #> add vs t2 | |
| 228 | | add vs ((v, _) `|-> t) = | |
| 229 | add (insert (op =) v vs) t | |
| 21012 | 230 | | add vs (INum _) = | 
| 231 | I | |
| 232 | | add vs (IChar _) = | |
| 233 | I | |
| 234 | | add vs (ICase ((td, _), bs)) = | |
| 235 | add vs td #> fold (fn (p, t) => add vs p #> add vs t) bs; | |
| 20896 | 236 | in add [] end; | 
| 20105 | 237 | |
| 20439 | 238 | fun eta_expand (c as (_, (_, ty)), ts) k = | 
| 19607 
07eeb832f28d
introduced characters for code generator; some improved code lemmas for some list functions
 haftmann parents: 
19597diff
changeset | 239 | let | 
| 20439 | 240 | val j = length ts; | 
| 19607 
07eeb832f28d
introduced characters for code generator; some improved code lemmas for some list functions
 haftmann parents: 
19597diff
changeset | 241 | val l = k - j; | 
| 
07eeb832f28d
introduced characters for code generator; some improved code lemmas for some list functions
 haftmann parents: 
19597diff
changeset | 242 | val tys = (curry Library.take l o curry Library.drop j o fst o unfold_fun) ty; | 
| 20896 | 243 | val ctxt = (fold o fold_varnames) Name.declare ts Name.context; | 
| 244 | val vs_tys = Name.names ctxt "a" tys; | |
| 20439 | 245 | in vs_tys `|--> IConst c `$$ ts @ map (fn (v, _) => IVar v) vs_tys end; | 
| 19607 
07eeb832f28d
introduced characters for code generator; some improved code lemmas for some list functions
 haftmann parents: 
19597diff
changeset | 246 | |
| 18304 | 247 | |
| 20896 | 248 | (** definitions, transactions **) | 
| 18170 | 249 | |
| 250 | (* type definitions *) | |
| 251 | ||
| 20456 | 252 | type typscheme = (vname * sort) list * itype; | 
| 18170 | 253 | datatype def = | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 254 | Bot | 
| 20456 | 255 | | Fun of (iterm list * iterm) list * typscheme | 
| 256 | | Datatype of (vname * sort) list * (string * itype list) list | |
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 257 | | Datatypecons of string | 
| 20456 | 258 | | Class of class list * (vname * (string * itype) list) | 
| 21082 | 259 | | Classop of class | 
| 20389 | 260 | | Classinst of (class * (string * (vname * sort) list)) | 
| 20466 | 261 | * ((class * (string * inst list list)) list | 
| 20456 | 262 | * (string * iterm) list); | 
| 19597 | 263 | val eq_def = (op =) : def * def -> bool; | 
| 18170 | 264 | |
| 20896 | 265 | type code = def Graph.T; | 
| 266 | type transact = Graph.key option * code; | |
| 21012 | 267 | exception FAIL of string list; | 
| 18360 | 268 | |
| 18170 | 269 | |
| 20896 | 270 | (* abstract code *) | 
| 18170 | 271 | |
| 20896 | 272 | val empty_code = Graph.empty : code; (*read: "depends on"*) | 
| 18170 | 273 | |
| 20896 | 274 | val get_def = Graph.get_node; | 
| 18170 | 275 | |
| 20896 | 276 | fun ensure_bot name = Graph.default_node (name, Bot); | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 277 | |
| 20896 | 278 | fun add_def_incr strict (name, Bot) code = | 
| 279 | (case the_default Bot (try (get_def code) name) | |
| 280 | of Bot => if strict then error "Attempted to add Bot to code" | |
| 281 | else Graph.map_node name (K Bot) code | |
| 282 | | _ => code) | |
| 283 | | add_def_incr _ (name, def) code = | |
| 284 | (case try (get_def code) name | |
| 285 | of NONE => Graph.new_node (name, def) code | |
| 286 | | SOME Bot => Graph.map_node name (K def) code | |
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 287 | | SOME def' => if eq_def (def, def') | 
| 20896 | 288 | then code | 
| 20389 | 289 |             else error ("Tried to overwrite definition " ^ quote name));
 | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 290 | |
| 20896 | 291 | fun add_dep (dep as (name1, name2)) = | 
| 292 | if name1 = name2 then I else Graph.add_edge dep; | |
| 18170 | 293 | |
| 20896 | 294 | val merge_code = Graph.join (fn _ => fn def12 => if eq_def def12 then fst def12 else Bot); | 
| 18170 | 295 | |
| 21012 | 296 | fun project_code hidden raw_selected code = | 
| 20466 | 297 | let | 
| 20896 | 298 | fun is_bot name = case get_def code name | 
| 299 | of Bot => true | |
| 300 | | _ => false; | |
| 301 | val names = subtract (op =) hidden (Graph.keys code); | |
| 21012 | 302 | val deleted = Graph.all_preds code (filter is_bot names); | 
| 303 | val selected = case raw_selected | |
| 304 | of NONE => names |> subtract (op =) deleted | |
| 305 | | SOME sel => sel | |
| 306 | |> subtract (op =) deleted | |
| 307 | |> subtract (op =) hidden | |
| 308 | |> Graph.all_succs code | |
| 309 | |> subtract (op =) deleted | |
| 310 | |> subtract (op =) hidden; | |
| 20191 | 311 | in | 
| 21012 | 312 | code | 
| 313 | |> Graph.project (member (op =) selected) | |
| 20191 | 314 | end; | 
| 315 | ||
| 18702 | 316 | fun check_samemodule names = | 
| 317 | fold (fn name => | |
| 318 | let | |
| 20896 | 319 | val module_name = (NameSpace.qualifier o NameSpace.qualifier) name | 
| 18702 | 320 | in | 
| 20896 | 321 | fn NONE => SOME module_name | 
| 322 | | SOME module_name' => if module_name = module_name' then SOME module_name | |
| 20386 | 323 |           else error ("Inconsistent name prefix for simultanous names: " ^ commas_quote names)
 | 
| 18702 | 324 | end | 
| 325 | ) names NONE; | |
| 326 | ||
| 327 | fun check_funeqs eqs = | |
| 328 | (fold (fn (pats, _) => | |
| 329 | let | |
| 330 | val l = length pats | |
| 331 | in | |
| 332 | fn NONE => SOME l | |
| 18850 | 333 | | SOME l' => if l = l' then SOME l | 
| 20389 | 334 | else error "Function definition with different number of arguments" | 
| 18702 | 335 | end | 
| 336 | ) eqs NONE; eqs); | |
| 337 | ||
| 21082 | 338 | fun check_prep_def code Bot = | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 339 | Bot | 
| 21082 | 340 | | check_prep_def code (Fun (eqs, d)) = | 
| 18702 | 341 | Fun (check_funeqs eqs, d) | 
| 21082 | 342 | | check_prep_def code (d as Datatype _) = | 
| 19038 | 343 | d | 
| 21082 | 344 | | check_prep_def code (Datatypecons dtco) = | 
| 20389 | 345 | error "Attempted to add bare datatype constructor" | 
| 21082 | 346 | | check_prep_def code (d as Class _) = | 
| 19038 | 347 | d | 
| 21082 | 348 | | check_prep_def code (Classop _) = | 
| 20389 | 349 | error "Attempted to add bare class member" | 
| 21082 | 350 | | check_prep_def code (d as Classinst ((class, (tyco, arity)), (_, memdefs))) = | 
| 18170 | 351 | let | 
| 21082 | 352 | val Class (_, (v, membrs)) = get_def code class; | 
| 18702 | 353 | val _ = if length memdefs > length memdefs | 
| 20389 | 354 | then error "Too many member definitions given" | 
| 18702 | 355 | else (); | 
| 20389 | 356 | fun check_memdef (m, _) = | 
| 357 | if AList.defined (op =) memdefs m | |
| 358 |           then () else error ("Missing definition for member " ^ quote m);
 | |
| 359 | val _ = map check_memdef memdefs; | |
| 360 | in d end | |
| 21082 | 361 | | check_prep_def code Classinstmember = | 
| 20389 | 362 | error "Attempted to add bare class instance member"; | 
| 18170 | 363 | |
| 19038 | 364 | fun postprocess_def (name, Datatype (_, constrs)) = | 
| 18702 | 365 | (check_samemodule (name :: map fst constrs); | 
| 366 | fold (fn (co, _) => | |
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 367 | add_def_incr true (co, Datatypecons name) | 
| 18702 | 368 | #> add_dep (co, name) | 
| 369 | #> add_dep (name, co) | |
| 370 | ) constrs | |
| 371 | ) | |
| 19038 | 372 | | postprocess_def (name, Class (_, (_, membrs))) = | 
| 18702 | 373 | (check_samemodule (name :: map fst membrs); | 
| 374 | fold (fn (m, _) => | |
| 21082 | 375 | add_def_incr true (m, Classop name) | 
| 18702 | 376 | #> add_dep (m, name) | 
| 377 | #> add_dep (name, m) | |
| 378 | ) membrs | |
| 379 | ) | |
| 380 | | postprocess_def _ = | |
| 381 | I; | |
| 18380 
9668764224a7
substantial improvements for class code generation
 haftmann parents: 
18361diff
changeset | 382 | |
| 19884 | 383 | |
| 384 | (* transaction protocol *) | |
| 18170 | 385 | |
| 21082 | 386 | fun ensure_def defgen strict msg name (dep, code) = | 
| 18170 | 387 | let | 
| 20389 | 388 | (*FIXME represent dependencies as tuple (name, name -> string), for better error msgs*) | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 389 | val msg' = (case dep | 
| 18702 | 390 | of NONE => msg | 
| 19884 | 391 | | SOME dep => msg ^ ", required for " ^ quote dep) | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 392 | ^ (if strict then " (strict)" else " (non-strict)"); | 
| 18702 | 393 | fun add_dp NONE = I | 
| 394 | | add_dp (SOME dep) = | |
| 20835 | 395 | tracing (fn _ => "adding dependency " ^ quote dep ^ " -> " ^ quote name) | 
| 18702 | 396 | #> add_dep (dep, name); | 
| 21082 | 397 | fun prep_def def code = | 
| 398 | (check_prep_def code def, code); | |
| 399 | fun invoke_generator name defgen code = | |
| 400 | defgen (SOME name, code) | |
| 21012 | 401 | handle FAIL msgs => | 
| 402 | if strict then raise FAIL (msg' :: msgs) | |
| 21082 | 403 | else (Bot, code); | 
| 18170 | 404 | in | 
| 21082 | 405 | code | 
| 406 | |> (if can (get_def code) name | |
| 18702 | 407 | then | 
| 20835 | 408 | tracing (fn _ => "asserting node " ^ quote name) | 
| 18702 | 409 | #> add_dp dep | 
| 410 | else | |
| 20835 | 411 | tracing (fn _ => "allocating node " ^ quote name ^ (if strict then " (strict)" else " (non-strict)")) | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 412 | #> ensure_bot name | 
| 18702 | 413 | #> add_dp dep | 
| 20835 | 414 | #> tracing (fn _ => "creating node " ^ quote name) | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 415 | #> invoke_generator name defgen | 
| 18702 | 416 | #-> (fn def => prep_def def) | 
| 417 | #-> (fn def => | |
| 20896 | 418 | tracing (fn _ => "adding") | 
| 19816 
a8c8ed1c85e0
removed 'primitive definitions' added (non)strict generation, minor fixes
 haftmann parents: 
19785diff
changeset | 419 | #> add_def_incr strict (name, def) | 
| 20835 | 420 | #> tracing (fn _ => "postprocessing") | 
| 18702 | 421 | #> postprocess_def (name, def) | 
| 20835 | 422 | #> tracing (fn _ => "adding done") | 
| 18702 | 423 | )) | 
| 424 | |> pair dep | |
| 18170 | 425 | end; | 
| 426 | ||
| 21082 | 427 | fun succeed some (_, code) = (some, code); | 
| 19884 | 428 | |
| 21082 | 429 | fun fail msg (_, code) = raise FAIL [msg]; | 
| 19884 | 430 | |
| 431 | fun message msg f trns = | |
| 21012 | 432 | f trns handle FAIL msgs => | 
| 433 | raise FAIL (msg :: msgs); | |
| 19884 | 434 | |
| 21082 | 435 | fun start_transact init f code = | 
| 18231 | 436 | let | 
| 18963 | 437 | fun handle_fail f x = | 
| 438 | (f x | |
| 21012 | 439 | handle FAIL msgs => | 
| 20389 | 440 |         (error o cat_lines) ("Code generation failed, while:" :: msgs))
 | 
| 18231 | 441 | in | 
| 21082 | 442 | code | 
| 19884 | 443 | |> (if is_some init then ensure_bot (the init) else I) | 
| 444 | |> pair init | |
| 18231 | 445 | |> handle_fail f | 
| 21082 | 446 | |-> (fn x => fn (_, code) => (x, code)) | 
| 18231 | 447 | end; | 
| 18172 | 448 | |
| 21160 | 449 | fun add_eval_def (name, t) code = | 
| 450 | code | |
| 451 |   |> Graph.new_node (name, Fun ([([], t)], ([("_", [])], ITyVar "_")))
 | |
| 452 | |> fold (curry Graph.add_edge name) (Graph.keys code); | |
| 18172 | 453 | |
| 21082 | 454 | |
| 455 | (** variable name contexts **) | |
| 456 | ||
| 457 | type var_ctxt = string Symtab.table * Name.context; | |
| 458 | ||
| 459 | fun make_vars names = (fold (fn name => Symtab.update_new (name, name)) names Symtab.empty, | |
| 460 | Name.make_context names); | |
| 461 | ||
| 462 | fun intro_vars names (namemap, namectxt) = | |
| 463 | let | |
| 464 | val (names', namectxt') = Name.variants names namectxt; | |
| 465 | val namemap' = fold2 (curry Symtab.update) names names' namemap; | |
| 466 | in (namemap', namectxt') end; | |
| 467 | ||
| 468 | fun lookup_var (namemap, _) name = case Symtab.lookup namemap name | |
| 469 | of SOME name' => name' | |
| 470 |   | NONE => error ("invalid name in context: " ^ quote name);
 | |
| 471 | ||
| 20896 | 472 | end; (*struct*) | 
| 18885 | 473 | |
| 18216 | 474 | |
| 19300 | 475 | structure BasicCodegenThingol: BASIC_CODEGEN_THINGOL = CodegenThingol; |