comparison src/cjr_print.sml @ 182:d11754ffe252

Compiled pattern matching to C
author Adam Chlipala <adamc@hcoop.net>
date Sun, 03 Aug 2008 12:43:20 -0400
parents 31dfab1d4050
children 19ee24bffbc0
comparison
equal deleted inserted replaced
181:31dfab1d4050 182:d11754ffe252
83 83
84 fun p_enamed env n = 84 fun p_enamed env n =
85 string ("__lwn_" ^ #1 (E.lookupENamed env n) ^ "_" ^ Int.toString n) 85 string ("__lwn_" ^ #1 (E.lookupENamed env n) ^ "_" ^ Int.toString n)
86 handle CjrEnv.UnboundNamed _ => string ("__lwn_UNBOUND_" ^ Int.toString n) 86 handle CjrEnv.UnboundNamed _ => string ("__lwn_UNBOUND_" ^ Int.toString n)
87 87
88 fun p_exp' par env (e, _) = 88 fun p_con_named env n =
89 string ("__lwc_" ^ #1 (E.lookupConstructor env n) ^ "_" ^ Int.toString n)
90 handle CjrEnv.UnboundNamed _ => string ("__lwc_UNBOUND_" ^ Int.toString n)
91
92 fun p_pat_preamble env (p, _) =
93 case p of
94 PWild => (box [],
95 env)
96 | PVar (x, t) => (box [p_typ env t,
97 space,
98 string "__lwr_",
99 string x,
100 string "_",
101 string (Int.toString (E.countERels env)),
102 string ";",
103 newline],
104 env)
105 | PPrim _ => (box [], env)
106 | PCon (_, NONE) => (box [], env)
107 | PCon (_, SOME p) => p_pat_preamble env p
108 | PRecord xps =>
109 foldl (fn ((_, p, _), (pp, env)) =>
110 let
111 val (pp', env) = p_pat_preamble env p
112 in
113 (box [pp', pp], env)
114 end) (box [], env) xps
115
116 fun p_patCon env pc =
117 case pc of
118 PConVar n => p_con_named env n
119 | PConFfi _ => raise Fail "CjrPrint PConFfi"
120
121 fun p_pat (env, exit, depth) (p, _) =
122 case p of
123 PWild =>
124 (box [], env)
125 | PVar (x, t) =>
126 (box [string "__lwr_",
127 string x,
128 string "_",
129 string (Int.toString (E.countERels env)),
130 space,
131 string "=",
132 space,
133 string "disc",
134 string (Int.toString depth),
135 string ";"],
136 E.pushERel env x t)
137 | PPrim (Prim.Int n) =>
138 (box [string "if",
139 space,
140 string "(disc",
141 string (Int.toString depth),
142 space,
143 string "!=",
144 space,
145 Prim.p_t (Prim.Int n),
146 string ")",
147 space,
148 exit],
149 env)
150 | PPrim (Prim.String s) =>
151 (box [string "if",
152 space,
153 string "(strcmp(disc",
154 string (Int.toString depth),
155 string ",",
156 space,
157 Prim.p_t (Prim.String s),
158 string "))",
159 space,
160 exit],
161 env)
162 | PPrim _ => raise Fail "CjrPrint: Disallowed PPrim primitive"
163
164 | PCon (pc, po) =>
165 let
166 val (p, env) =
167 case po of
168 NONE => (box [], env)
169 | SOME p =>
170 let
171 val (p, env) = p_pat (env, exit, depth + 1) p
172
173 val (x, to) = case pc of
174 PConVar n =>
175 let
176 val (x, to, _) = E.lookupConstructor env n
177 in
178 (x, to)
179 end
180 | PConFfi _ => raise Fail "PConFfi"
181
182 val t = case to of
183 NONE => raise Fail "CjrPrint: Constructor mismatch"
184 | SOME t => t
185 in
186 (box [string "{",
187 newline,
188 p_typ env t,
189 space,
190 string "disc",
191 string (Int.toString (depth + 1)),
192 space,
193 string "=",
194 space,
195 string "disc",
196 string (Int.toString depth),
197 string "->data.__lwc_",
198 string x,
199 string ";",
200 newline,
201 p,
202 newline,
203 string "}"],
204 env)
205 end
206 in
207 (box [string "if",
208 space,
209 string "(disc",
210 string (Int.toString depth),
211 string "->tag",
212 space,
213 string "!=",
214 space,
215 p_patCon env pc,
216 string ")",
217 space,
218 exit,
219 newline,
220 p],
221 env)
222 end
223
224 | PRecord xps =>
225 let
226 val (xps, env) =
227 ListUtil.foldlMap (fn ((x, p, t), env) =>
228 let
229 val (p, env) = p_pat (env, exit, depth + 1) p
230
231 val p = box [string "{",
232 newline,
233 p_typ env t,
234 space,
235 string "disc",
236 string (Int.toString (depth + 1)),
237 space,
238 string "=",
239 space,
240 string "disc",
241 string (Int.toString depth),
242 string ".",
243 string x,
244 string ";",
245 newline,
246 p,
247 newline,
248 string "}"]
249 in
250 (p, env)
251 end) env xps
252 in
253 (p_list_sep newline (fn x => x) xps,
254 env)
255 end
256
257 local
258 val count = ref 0
259 in
260 fun newGoto () =
261 let
262 val r = !count
263 in
264 count := r + 1;
265 string ("L" ^ Int.toString r)
266 end
267 end
268
269 fun p_exp' par env (e, loc) =
89 case e of 270 case e of
90 EPrim p => Prim.p_t p 271 EPrim p => Prim.p_t p
91 | ERel n => p_rel env n 272 | ERel n => p_rel env n
92 | ENamed n => p_enamed env n 273 | ENamed n => p_enamed env n
93 | ECon (n, eo) => 274 | ECon (n, eo) =>
94 let 275 let
95 val (x, _, dn) = E.lookupConstructor env n 276 val (x, _, dn) = E.lookupConstructor env n
96 val (dx, _) = E.lookupDatatype env dn 277 val (dx, _) = E.lookupDatatype env dn
97 in 278 in
98 box [string "{(", 279 box [string "({",
99 newline, 280 newline,
100 string "struct", 281 string "struct",
101 space, 282 space,
102 string "__lwd_", 283 string "__lwd_",
103 string dx, 284 string dx,
121 string ("__lwc_" ^ x ^ "_" ^ Int.toString n), 302 string ("__lwc_" ^ x ^ "_" ^ Int.toString n),
122 string ";", 303 string ";",
123 newline, 304 newline,
124 case eo of 305 case eo of
125 NONE => box [] 306 NONE => box []
126 | SOME e => box [string "tmp->data.", 307 | SOME e => box [string "tmp->data.__lwc_",
127 string x, 308 string x,
128 space, 309 space,
129 string "=", 310 string "=",
130 space, 311 space,
131 p_exp env e, 312 p_exp env e,
178 string "tmp;", 359 string "tmp;",
179 space, 360 space,
180 string "})" ] 361 string "})" ]
181 | EField (e, x) => 362 | EField (e, x) =>
182 box [p_exp' true env e, 363 box [p_exp' true env e,
183 string ".", 364 string ".__lwf_",
184 string x] 365 string x]
185 366
186 | ECase _ => raise Fail "CjrPrint ECase" 367 | ECase (e, pes, {disc, result}) =>
368 let
369 val final = newGoto ()
370
371 val body = foldl (fn ((p, e), body) =>
372 let
373 val exit = newGoto ()
374 val (pr, _) = p_pat_preamble env p
375 val (p, env) = p_pat (env,
376 box [string "goto",
377 space,
378 exit,
379 string ";"],
380 0) p
381 in
382 box [body,
383 box [string "{",
384 newline,
385 pr,
386 newline,
387 p,
388 newline,
389 string "result",
390 space,
391 string "=",
392 space,
393 p_exp env e,
394 string ";",
395 newline,
396 string "goto",
397 space,
398 final,
399 string ";",
400 newline,
401 string "}"],
402 newline,
403 exit,
404 string ":",
405 newline]
406 end) (box []) pes
407 in
408 box [string "({",
409 newline,
410 p_typ env disc,
411 space,
412 string "disc0",
413 space,
414 string "=",
415 space,
416 p_exp env e,
417 string ";",
418 newline,
419 p_typ env result,
420 space,
421 string "result;",
422 newline,
423 body,
424 string "lw_error(ctx, FATAL, \"",
425 string (ErrorMsg.spanToString loc),
426 string ": pattern match failure\");",
427 newline,
428 final,
429 string ":",
430 space,
431 string "result;",
432 newline,
433 string "})"]
434 end
187 435
188 | EWrite e => box [string "(lw_write(ctx, ", 436 | EWrite e => box [string "(lw_write(ctx, ",
189 p_exp env e, 437 p_exp env e,
190 string "), lw_unit_v)"] 438 string "), lw_unit_v)"]
191 439
234 space, 482 space,
235 string "{", 483 string "{",
236 newline, 484 newline,
237 p_list_sep (box []) (fn (x, t) => box [p_typ env t, 485 p_list_sep (box []) (fn (x, t) => box [p_typ env t,
238 space, 486 space,
487 string "__lwf_",
239 string x, 488 string x,
240 string ";", 489 string ";",
241 newline]) xts, 490 newline]) xts,
242 string "};"] 491 string "};"]
243 | DDatatype (x, n, xncs) => 492 | DDatatype (x, n, xncs) =>
536 newline, 785 newline,
537 string "if (request[0] == '/') ++request;", 786 string "if (request[0] == '/') ++request;",
538 newline, 787 newline,
539 case to of 788 case to of
540 NONE => box [] 789 NONE => box []
541 | SOME t => box [string "tmp->data.", 790 | SOME t => box [string "tmp->data.__lwc_",
542 string x', 791 string x',
543 space, 792 space,
544 string "=", 793 string "=",
545 space, 794 space,
546 unurlify t, 795 unurlify t,