Mercurial > urweb
comparison src/cjr_print.sml @ 1431:4a6f84092399
Represent 'unit' as C 'int'; change pattern match compilation to avoid 'goto'; change Postgres prepared statement compilation to make life easier for the GCC escape analysis; all this in support of better tail call optimization
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Thu, 10 Mar 2011 18:51:15 -0500 |
parents | 7d963b8019e6 |
children | 6064ddd90ca6 |
comparison
equal
deleted
inserted
replaced
1430:36c0a1be3f5a | 1431:4a6f84092399 |
---|---|
71 | 71 |
72 fun p_typ' par env (t, loc) = | 72 fun p_typ' par env (t, loc) = |
73 case t of | 73 case t of |
74 TFun (t1, t2) => (EM.errorAt loc "Function type remains"; | 74 TFun (t1, t2) => (EM.errorAt loc "Function type remains"; |
75 string "<FUNCTION>") | 75 string "<FUNCTION>") |
76 | TRecord 0 => string "uw_unit" | |
76 | TRecord i => box [string "struct", | 77 | TRecord i => box [string "struct", |
77 space, | 78 space, |
78 string "__uws_", | 79 string "__uws_", |
79 string (Int.toString i)] | 80 string (Int.toString i)] |
80 | TDatatype (Enum, n, _) => | 81 | TDatatype (Enum, n, _) => |
153 fun p_patCon env pc = | 154 fun p_patCon env pc = |
154 case pc of | 155 case pc of |
155 PConVar n => p_con_named env n | 156 PConVar n => p_con_named env n |
156 | PConFfi {mod = m, con, ...} => string ("uw_" ^ ident m ^ "_" ^ ident con) | 157 | PConFfi {mod = m, con, ...} => string ("uw_" ^ ident m ^ "_" ^ ident con) |
157 | 158 |
158 fun p_pat (env, exit, depth) (p, loc) = | 159 fun p_patMatch (env, disc) (p, loc) = |
159 case p of | 160 case p of |
160 PWild => | 161 PWild => string "1" |
161 (box [], env) | 162 | PVar _ => string "1" |
162 | PVar (x, t) => | 163 | PPrim (Prim.Int n) => box [string ("(" ^ disc), |
163 (box [string "__uwr_", | 164 space, |
164 p_ident x, | 165 string "==", |
165 string "_", | 166 space, |
166 string (Int.toString (E.countERels env)), | 167 Prim.p_t_GCC (Prim.Int n), |
167 space, | 168 string ")"] |
168 string "=", | 169 | PPrim (Prim.String s) => box [string ("!strcmp(" ^ disc), |
169 space, | 170 string ",", |
170 string "disc", | 171 space, |
171 string (Int.toString depth), | 172 Prim.p_t_GCC (Prim.String s), |
172 string ";"], | 173 string ")"] |
173 E.pushERel env x t) | 174 | PPrim (Prim.Char ch) => box [string ("(" ^ disc), |
174 | PPrim (Prim.Int n) => | 175 space, |
175 (box [string "if", | 176 string "==", |
176 space, | 177 space, |
177 string "(disc", | 178 Prim.p_t_GCC (Prim.Char ch), |
178 string (Int.toString depth), | 179 string ")"] |
179 space, | |
180 string "!=", | |
181 space, | |
182 Prim.p_t_GCC (Prim.Int n), | |
183 string ")", | |
184 space, | |
185 exit], | |
186 env) | |
187 | PPrim (Prim.String s) => | |
188 (box [string "if", | |
189 space, | |
190 string "(strcmp(disc", | |
191 string (Int.toString depth), | |
192 string ",", | |
193 space, | |
194 Prim.p_t_GCC (Prim.String s), | |
195 string "))", | |
196 space, | |
197 exit], | |
198 env) | |
199 | PPrim (Prim.Char ch) => | |
200 (box [string "if", | |
201 space, | |
202 string "(disc", | |
203 string (Int.toString depth), | |
204 space, | |
205 string "!=", | |
206 space, | |
207 Prim.p_t_GCC (Prim.Char ch), | |
208 string ")", | |
209 space, | |
210 exit], | |
211 env) | |
212 | PPrim _ => raise Fail "CjrPrint: Disallowed PPrim primitive" | 180 | PPrim _ => raise Fail "CjrPrint: Disallowed PPrim primitive" |
213 | 181 |
214 | PCon (dk, pc, po) => | 182 | PCon (dk, pc, po) => |
215 let | 183 let |
216 val (p, env) = | 184 val p = |
217 case po of | 185 case po of |
218 NONE => (box [], env) | 186 NONE => box [] |
219 | SOME p => | 187 | SOME p => |
220 let | 188 let |
221 val (p, env) = p_pat (env, exit, depth + 1) p | |
222 | |
223 val (x, to) = case pc of | 189 val (x, to) = case pc of |
224 PConVar n => | 190 PConVar n => |
225 let | 191 let |
226 val (x, to, _) = E.lookupConstructor env n | 192 val (x, to, _) = E.lookupConstructor env n |
227 in | 193 in |
231 ("uw_" ^ ident m ^ "_" ^ ident con, arg) | 197 ("uw_" ^ ident m ^ "_" ^ ident con, arg) |
232 | 198 |
233 val t = case to of | 199 val t = case to of |
234 NONE => raise Fail "CjrPrint: Constructor mismatch" | 200 NONE => raise Fail "CjrPrint: Constructor mismatch" |
235 | SOME t => t | 201 | SOME t => t |
202 | |
203 val x = case pc of | |
204 PConVar n => | |
205 let | |
206 val (x, _, _) = E.lookupConstructor env n | |
207 in | |
208 "uw_" ^ ident x | |
209 end | |
210 | PConFfi {mod = m, con, ...} => | |
211 "uw_" ^ ident m ^ "_" ^ ident con | |
212 | |
213 val disc' = case dk of | |
214 Enum => raise Fail "CjrPrint: Looking at argument of no-argument constructor" | |
215 | Default => disc ^ "->data." ^ x | |
216 | Option => | |
217 if isUnboxable t then | |
218 disc | |
219 else | |
220 "(*" ^ disc ^ ")" | |
221 | |
222 val p = p_patMatch (env, disc') p | |
236 in | 223 in |
237 (box [string "{", | 224 box [space, |
238 newline, | 225 string "&&", |
239 p_typ env t, | 226 space, |
240 space, | 227 p] |
241 string "disc", | |
242 string (Int.toString (depth + 1)), | |
243 space, | |
244 string "=", | |
245 space, | |
246 case dk of | |
247 Enum => raise Fail "CjrPrint: Looking at argument of no-argument constructor" | |
248 | Default => box [string "disc", | |
249 string (Int.toString depth), | |
250 string "->data.", | |
251 string x] | |
252 | Option => | |
253 if isUnboxable t then | |
254 box [string "disc", | |
255 string (Int.toString depth)] | |
256 else | |
257 box [string "*disc", | |
258 string (Int.toString depth)], | |
259 string ";", | |
260 newline, | |
261 p, | |
262 newline, | |
263 string "}"], | |
264 env) | |
265 end | 228 end |
266 in | 229 in |
267 (box [string "if", | 230 box [string disc, |
268 space, | 231 case (dk, po) of |
269 string "(disc", | 232 (Enum, _) => box [space, |
270 string (Int.toString depth), | 233 string "==", |
271 case (dk, po) of | 234 space, |
272 (Enum, _) => box [space, | 235 p_patCon env pc] |
273 string "!=", | 236 | (Default, _) => box [string "->tag", |
274 space, | 237 space, |
275 p_patCon env pc] | 238 string "==", |
276 | (Default, _) => box [string "->tag", | 239 space, |
277 space, | 240 p_patCon env pc] |
278 string "!=", | 241 | (Option, NONE) => box [space, |
279 space, | 242 string "==", |
280 p_patCon env pc] | 243 space, |
281 | (Option, NONE) => box [space, | 244 string "NULL"] |
282 string "!=", | 245 | (Option, SOME _) => box [space, |
283 space, | 246 string "!=", |
284 string "NULL"] | 247 space, |
285 | (Option, SOME _) => box [space, | 248 string "NULL"], |
286 string "==", | 249 p] |
287 space, | 250 end |
288 string "NULL"], | 251 |
289 string ")", | 252 | PRecord xps => |
290 space, | 253 p_list_sep (box [space, string "&&", space]) (fn (x, p, _) => p_patMatch (env, disc ^ ".__uwf_" ^ ident x) p) xps |
291 exit, | 254 |
292 newline, | 255 | PNone _ => |
293 p], | 256 box [string disc, |
294 env) | 257 space, |
258 string "==", | |
259 space, | |
260 string "NULL"] | |
261 | |
262 | PSome (t, p) => | |
263 let | |
264 val disc' = if isUnboxable t then | |
265 disc | |
266 else | |
267 "(*" ^ disc ^ ")" | |
268 | |
269 val p = p_patMatch (env, disc') p | |
270 in | |
271 box [string disc, | |
272 space, | |
273 string "!=", | |
274 space, | |
275 string "NULL", | |
276 space, | |
277 string "&&", | |
278 space, | |
279 p] | |
280 end | |
281 | |
282 fun p_patBind (env, disc) (p, loc) = | |
283 case p of | |
284 PWild => | |
285 (box [], env) | |
286 | PVar (x, t) => | |
287 (box [p_typ env t, | |
288 space, | |
289 string "__uwr_", | |
290 p_ident x, | |
291 string "_", | |
292 string (Int.toString (E.countERels env)), | |
293 space, | |
294 string "=", | |
295 space, | |
296 string disc, | |
297 string ";", | |
298 newline], | |
299 E.pushERel env x t) | |
300 | PPrim _ => (box [], env) | |
301 | |
302 | PCon (_, _, NONE) => (box [], env) | |
303 | |
304 | PCon (dk, pc, SOME p) => | |
305 let | |
306 val (x, to) = case pc of | |
307 PConVar n => | |
308 let | |
309 val (x, to, _) = E.lookupConstructor env n | |
310 in | |
311 ("uw_" ^ ident x, to) | |
312 end | |
313 | PConFfi {mod = m, con, arg, ...} => | |
314 ("uw_" ^ ident m ^ "_" ^ ident con, arg) | |
315 | |
316 val t = case to of | |
317 NONE => raise Fail "CjrPrint: Constructor mismatch" | |
318 | SOME t => t | |
319 | |
320 val disc' = case dk of | |
321 Enum => raise Fail "CjrPrint: Looking at argument of no-argument constructor" | |
322 | Default => disc ^ "->data." ^ x | |
323 | Option => | |
324 if isUnboxable t then | |
325 disc | |
326 else | |
327 "(*" ^ disc ^ ")" | |
328 in | |
329 p_patBind (env, disc') p | |
295 end | 330 end |
296 | 331 |
297 | PRecord xps => | 332 | PRecord xps => |
298 let | 333 let |
299 val (xps, env) = | 334 val (xps, env) = |
300 ListUtil.foldlMap (fn ((x, p, t), env) => | 335 ListUtil.foldlMap (fn ((x, p, t), env) => p_patBind (env, disc ^ ".__uwf_" ^ ident x) p) |
301 let | 336 env xps |
302 val (p, env) = p_pat (env, exit, depth + 1) p | |
303 | |
304 val p = box [string "{", | |
305 newline, | |
306 p_typ env t, | |
307 space, | |
308 string "disc", | |
309 string (Int.toString (depth + 1)), | |
310 space, | |
311 string "=", | |
312 space, | |
313 string "disc", | |
314 string (Int.toString depth), | |
315 string ".__uwf_", | |
316 p_ident x, | |
317 string ";", | |
318 newline, | |
319 p, | |
320 newline, | |
321 string "}"] | |
322 in | |
323 (p, env) | |
324 end) env xps | |
325 in | 337 in |
326 (p_list_sep newline (fn x => x) xps, | 338 (p_list_sep (box []) (fn x => x) xps, |
327 env) | 339 env) |
328 end | 340 end |
329 | 341 |
330 | PNone t => | 342 | PNone _ => (box [], env) |
331 (box [string "if", | |
332 space, | |
333 string "(disc", | |
334 string (Int.toString depth), | |
335 space, | |
336 string "!=", | |
337 space, | |
338 string "NULL)", | |
339 space, | |
340 exit, | |
341 newline], | |
342 env) | |
343 | 343 |
344 | PSome (t, p) => | 344 | PSome (t, p) => |
345 let | 345 let |
346 val (p, env) = | 346 val disc' = if isUnboxable t then |
347 let | 347 disc |
348 val (p, env) = p_pat (env, exit, depth + 1) p | 348 else |
349 in | 349 "(*" ^ disc ^ ")" |
350 (box [string "{", | |
351 newline, | |
352 p_typ env t, | |
353 space, | |
354 string "disc", | |
355 string (Int.toString (depth + 1)), | |
356 space, | |
357 string "=", | |
358 space, | |
359 if isUnboxable t then | |
360 box [string "disc", | |
361 string (Int.toString depth)] | |
362 else | |
363 box [string "*disc", | |
364 string (Int.toString depth)], | |
365 string ";", | |
366 newline, | |
367 p, | |
368 newline, | |
369 string "}"], | |
370 env) | |
371 end | |
372 in | 350 in |
373 (box [string "if", | 351 p_patBind (env, disc') p |
374 space, | |
375 string "(disc", | |
376 string (Int.toString depth), | |
377 space, | |
378 string "==", | |
379 space, | |
380 string "NULL)", | |
381 space, | |
382 exit, | |
383 newline, | |
384 p], | |
385 env) | |
386 end | 352 end |
387 | |
388 local | |
389 val count = ref 0 | |
390 in | |
391 fun newGoto () = | |
392 let | |
393 val r = !count | |
394 in | |
395 count := r + 1; | |
396 string ("L" ^ Int.toString r) | |
397 end | |
398 end | |
399 | 353 |
400 fun patConInfo env pc = | 354 fun patConInfo env pc = |
401 case pc of | 355 case pc of |
402 PConVar n => | 356 PConVar n => |
403 let | 357 let |
1565 space, | 1519 space, |
1566 string s, | 1520 string s, |
1567 space, | 1521 space, |
1568 p_exp' true env e2]) | 1522 p_exp' true env e2]) |
1569 | 1523 |
1524 | ERecord (0, _) => string "0" | |
1525 | |
1570 | ERecord (i, xes) => box [string "({", | 1526 | ERecord (i, xes) => box [string "({", |
1571 space, | 1527 space, |
1572 string "struct", | 1528 string "struct", |
1573 space, | 1529 space, |
1574 string ("__uws_" ^ Int.toString i), | 1530 string ("__uws_" ^ Int.toString i), |
1589 box [p_exp' true env e, | 1545 box [p_exp' true env e, |
1590 string ".__uwf_", | 1546 string ".__uwf_", |
1591 p_ident x] | 1547 p_ident x] |
1592 | 1548 |
1593 | ECase (e, pes, {disc, result}) => | 1549 | ECase (e, pes, {disc, result}) => |
1594 let | 1550 box [string "({", |
1595 val final = newGoto () | 1551 newline, |
1596 | 1552 p_typ env disc, |
1597 val body = foldl (fn ((p, e), body) => | 1553 space, |
1598 let | 1554 string "disc", |
1599 val exit = newGoto () | 1555 space, |
1600 val (pr, _) = p_pat_preamble env p | 1556 string "=", |
1601 val (p, env) = p_pat (env, | 1557 space, |
1602 box [string "goto", | 1558 p_exp env e, |
1603 space, | 1559 string ";", |
1604 exit, | 1560 newline, |
1605 string ";"], | 1561 newline, |
1606 0) p | 1562 foldr (fn ((p, e), body) => |
1607 in | 1563 let |
1608 box [body, | 1564 val pm = p_patMatch (env, "disc") p |
1609 box [string "{", | 1565 val (pb, env) = p_patBind (env, "disc") p |
1610 newline, | 1566 in |
1611 pr, | 1567 box [pm, |
1612 newline, | 1568 space, |
1613 p, | 1569 string "?", |
1614 newline, | 1570 space, |
1615 string "result", | 1571 box [string "({", |
1616 space, | 1572 pb, |
1617 string "=", | 1573 p_exp env e, |
1618 space, | 1574 string ";", |
1619 p_exp env e, | 1575 newline, |
1620 string ";", | 1576 string "})"], |
1621 newline, | 1577 newline, |
1622 string "goto", | 1578 space, |
1623 space, | 1579 string ":", |
1624 final, | 1580 space, |
1625 string ";", | 1581 body] |
1626 newline, | 1582 end) (box [string "({", |
1627 string "}"], | 1583 newline, |
1628 newline, | 1584 p_typ env result, |
1629 exit, | 1585 space, |
1630 string ":", | 1586 string "tmp;", |
1631 newline] | 1587 newline, |
1632 end) (box []) pes | 1588 string "uw_error(ctx, FATAL, \"", |
1633 in | 1589 string (ErrorMsg.spanToString loc), |
1634 box [string "({", | 1590 string ": pattern match failure\");", |
1635 newline, | 1591 newline, |
1636 p_typ env disc, | 1592 string "tmp;", |
1637 space, | 1593 newline, |
1638 string "disc0", | 1594 string "})"]) pes, |
1639 space, | 1595 string ";", |
1640 string "=", | 1596 newline, |
1641 space, | 1597 string "})"] |
1642 p_exp env e, | |
1643 string ";", | |
1644 newline, | |
1645 p_typ env result, | |
1646 space, | |
1647 string "result;", | |
1648 newline, | |
1649 body, | |
1650 string "uw_error(ctx, FATAL, \"", | |
1651 string (ErrorMsg.spanToString loc), | |
1652 string ": pattern match failure\");", | |
1653 newline, | |
1654 final, | |
1655 string ":", | |
1656 space, | |
1657 string "result;", | |
1658 newline, | |
1659 string "})"] | |
1660 end | |
1661 | 1598 |
1662 | EWrite e => box [string "(uw_write(ctx, ", | 1599 | EWrite e => box [string "(uw_write(ctx, ", |
1663 p_exp env e, | 1600 p_exp env e, |
1664 string "), uw_unit_v)"] | 1601 string "), 0)"] |
1665 | 1602 |
1666 | ESeq (e1, e2) => | 1603 | ESeq (e1, e2) => |
1667 let | 1604 let |
1668 val useRegion = potentiallyFancy e1 | 1605 val useRegion = potentiallyFancy e1 |
1669 in | 1606 in |
1902 newline, | 1839 newline, |
1903 string "uw_end_region(ctx);", | 1840 string "uw_end_region(ctx);", |
1904 newline, | 1841 newline, |
1905 | 1842 |
1906 case mode of | 1843 case mode of |
1907 Settings.Error => string "uw_unit_v;" | 1844 Settings.Error => string "0;" |
1908 | Settings.None => string "uw_dup_and_clear_error_message(ctx);", | 1845 | Settings.None => string "uw_dup_and_clear_error_message(ctx);", |
1909 | 1846 |
1910 newline, | 1847 newline, |
1911 string "}))"] | 1848 string "}))"] |
1912 | 1849 |
1940 seqE = p_exp env seq, | 1877 seqE = p_exp env seq, |
1941 count = p_exp env count}, | 1878 count = p_exp env count}, |
1942 newline, | 1879 newline, |
1943 newline, | 1880 newline, |
1944 | 1881 |
1945 string "uw_unit_v;", | 1882 string "0;", |
1946 newline, | 1883 newline, |
1947 string "})"] | 1884 string "})"] |
1948 | 1885 |
1949 | EUnurlify (e, t, true) => | 1886 | EUnurlify (e, t, true) => |
1950 let | 1887 let |
2622 p_ident x, | 2559 p_ident x, |
2623 string ";", | 2560 string ";", |
2624 newline]) xts), | 2561 newline]) xts), |
2625 newline, | 2562 newline, |
2626 box (map getInput xts), | 2563 box (map getInput xts), |
2627 string "struct __uws_", | 2564 case i of |
2628 string (Int.toString i), | 2565 0 => string "uw_unit uw_inputs;" |
2629 space, | 2566 | _ => box [string "struct __uws_", |
2630 string "uw_inputs", | 2567 string (Int.toString i), |
2631 space, | 2568 space, |
2632 string "= {", | 2569 string "uw_inputs", |
2633 newline, | 2570 space, |
2634 box (map (fn (x, _) => box [string "uw_input_", | 2571 string "= {", |
2635 p_ident x, | 2572 newline, |
2636 string ",", | 2573 box (map (fn (x, _) => box [string "uw_input_", |
2637 newline]) xts), | 2574 p_ident x, |
2638 string "};", | 2575 string ",", |
2576 newline]) xts), | |
2577 string "};"], | |
2639 newline], | 2578 newline], |
2640 box [string ",", | 2579 box [string ",", |
2641 space, | 2580 space, |
2642 string "uw_inputs"], | 2581 string "uw_inputs"], |
2643 SOME xts) | 2582 SOME xts) |
2778 p_list_sep (box [string ",", space]) | 2717 p_list_sep (box [string ",", space]) |
2779 (fn x => x) | 2718 (fn x => x) |
2780 (string "ctx" | 2719 (string "ctx" |
2781 :: ListUtil.mapi (fn (i, _) => string ("arg" ^ Int.toString i)) ts), | 2720 :: ListUtil.mapi (fn (i, _) => string ("arg" ^ Int.toString i)) ts), |
2782 inputsVar, | 2721 inputsVar, |
2783 string ", uw_unit_v);", | 2722 string ", 0);", |
2784 newline, | 2723 newline, |
2785 box (case ek of | 2724 box (case ek of |
2786 Core.Rpc _ => [urlify env ran] | 2725 Core.Rpc _ => [urlify env ran] |
2787 | _ => [string "uw_write(ctx, \"</html>\");", | 2726 | _ => [string "uw_write(ctx, \"</html>\");", |
2788 newline]), | 2727 newline]), |
3010 string (Int.toString i), | 2949 string (Int.toString i), |
3011 string "(uw_context ctx) {", | 2950 string "(uw_context ctx) {", |
3012 newline, | 2951 newline, |
3013 box [string "uw_unit __uwr_", | 2952 box [string "uw_unit __uwr_", |
3014 string x1, | 2953 string x1, |
3015 string "_0 = uw_unit_v, __uwr_", | 2954 string "_0 = 0, __uwr_", |
3016 string x2, | 2955 string x2, |
3017 string "_1 = uw_unit_v;", | 2956 string "_1 = 0;", |
3018 newline, | 2957 newline, |
3019 p_exp (E.pushERel (E.pushERel env x1 dummyt) x2 dummyt) e, | 2958 p_exp (E.pushERel (E.pushERel env x1 dummyt) x2 dummyt) e, |
3020 string ";", | 2959 string ";", |
3021 newline], | 2960 newline], |
3022 string "}", | 2961 string "}", |
3112 string x1, | 3051 string x1, |
3113 string "_0 = cli;", | 3052 string "_0 = cli;", |
3114 newline, | 3053 newline, |
3115 string "uw_unit __uwr_", | 3054 string "uw_unit __uwr_", |
3116 string x2, | 3055 string x2, |
3117 string "_1 = uw_unit_v;", | 3056 string "_1 = 0;", |
3118 newline, | 3057 newline, |
3119 p_exp (E.pushERel (E.pushERel env x1 (TFfi ("Basis", "client"), ErrorMsg.dummySpan)) | 3058 p_exp (E.pushERel (E.pushERel env x1 (TFfi ("Basis", "client"), ErrorMsg.dummySpan)) |
3120 x2 dummyt) e, | 3059 x2 dummyt) e, |
3121 string ";", | 3060 string ";", |
3122 newline, | 3061 newline, |
3136 newline, | 3075 newline, |
3137 box [p_list_sep (box []) (fn (x1, x2, e) => box [string "({", | 3076 box [p_list_sep (box []) (fn (x1, x2, e) => box [string "({", |
3138 newline, | 3077 newline, |
3139 string "uw_unit __uwr_", | 3078 string "uw_unit __uwr_", |
3140 string x1, | 3079 string x1, |
3141 string "_0 = uw_unit_v, __uwr_", | 3080 string "_0 = 0, __uwr_", |
3142 string x2, | 3081 string x2, |
3143 string "_1 = uw_unit_v;", | 3082 string "_1 = 0;", |
3144 newline, | 3083 newline, |
3145 p_exp (E.pushERel (E.pushERel env x1 dummyt) x2 dummyt) e, | 3084 p_exp (E.pushERel (E.pushERel env x1 dummyt) x2 dummyt) e, |
3146 string ";", | 3085 string ";", |
3147 newline, | 3086 newline, |
3148 string "});", | 3087 string "});", |
3149 newline]) initializers, | 3088 newline]) initializers, |
3150 if hasDb then | 3089 if hasDb then |
3151 box [p_enamed env (!initialize), | 3090 box [p_enamed env (!initialize), |
3152 string "(ctx, uw_unit_v);", | 3091 string "(ctx, 0);", |
3153 newline] | 3092 newline] |
3154 else | 3093 else |
3155 box []], | 3094 box []], |
3156 string "}", | 3095 string "}", |
3157 newline, | 3096 newline, |
3160 NONE => box [] | 3099 NONE => box [] |
3161 | SOME n => box [string "static void uw_onError(uw_context ctx, char *msg) {", | 3100 | SOME n => box [string "static void uw_onError(uw_context ctx, char *msg) {", |
3162 newline, | 3101 newline, |
3163 box [string "uw_write(ctx, ", | 3102 box [string "uw_write(ctx, ", |
3164 p_enamed env n, | 3103 p_enamed env n, |
3165 string "(ctx, msg, uw_unit_v));", | 3104 string "(ctx, msg, 0));", |
3166 newline], | 3105 newline], |
3167 string "}", | 3106 string "}", |
3168 newline, | 3107 newline, |
3169 newline], | 3108 newline], |
3170 | 3109 |