comparison src/cjr_print.sml @ 144:f0d3402184d1

Simple forms work
author Adam Chlipala <adamc@hcoop.net>
date Tue, 22 Jul 2008 15:12:20 -0400
parents 4b9c2bd6157c
children e52dfb1e6b19
comparison
equal deleted inserted replaced
143:4b9c2bd6157c 144:f0d3402184d1
35 open Cjr 35 open Cjr
36 36
37 structure E = CjrEnv 37 structure E = CjrEnv
38 structure EM = ErrorMsg 38 structure EM = ErrorMsg
39 39
40 structure SK = struct
41 type ord_key = string
42 val compare = String.compare
43 end
44
45 structure SS = BinarySetFn(SK)
46 structure SM = BinaryMapFn(SK)
47 structure IS = IntBinarySet
48
49 structure CM = BinaryMapFn(struct
50 type ord_key = char
51 val compare = Char.compare
52 end)
53
40 val debug = ref false 54 val debug = ref false
41 55
42 val dummyTyp = (TNamed 0, ErrorMsg.dummySpan) 56 val dummyTyp = (TNamed 0, ErrorMsg.dummySpan)
43 57
44 fun p_typ' par env (t, loc) = 58 fun p_typ' par env (t, loc) =
206 newline, 220 newline,
207 p_list_sep newline (p_fun env) vis, 221 p_list_sep newline (p_fun env) vis,
208 newline] 222 newline]
209 end 223 end
210 224
211 fun unurlify env (t, loc) = 225 datatype 'a search =
212 case t of 226 Found of 'a
213 TFfi ("Basis", "int") => string "lw_unurlifyInt(&request)" 227 | NotFound
214 | TFfi ("Basis", "float") => string "lw_unurlifyFloat(&request)" 228 | Error
215 | TFfi ("Basis", "string") => string "lw_unurlifyString(ctx, &request)" 229
216
217 | TRecord 0 => string "lw_unit_v"
218 | TRecord i =>
219 let
220 val xts = E.lookupStruct env i
221 in
222 box [string "({",
223 newline,
224 box (map (fn (x, t) =>
225 box [p_typ env t,
226 space,
227 string x,
228 space,
229 string "=",
230 space,
231 unurlify env t,
232 string ";",
233 newline]) xts),
234 string "struct",
235 space,
236 string "__lws_",
237 string (Int.toString i),
238 space,
239 string "__lw_tmp",
240 space,
241 string "=",
242 space,
243 string "{",
244 space,
245 p_list_sep (box [string ",", space]) (fn (x, _) => string x) xts,
246 space,
247 string "};",
248 newline,
249 string "__lw_tmp;",
250 newline,
251 string "})"]
252 end
253
254 | _ => (ErrorMsg.errorAt loc "Unable to choose a URL decoding function";
255 space)
256
257 fun p_page env (s, n, ts) =
258 box [string "if (!strncmp(request, \"",
259 string (String.toString s),
260 string "\", ",
261 string (Int.toString (size s)),
262 string ")) {",
263 newline,
264 string "request += ",
265 string (Int.toString (size s)),
266 string ";",
267 newline,
268 string "if (*request == '/') ++request;",
269 newline,
270 box [string "{",
271 newline,
272 box (ListUtil.mapi (fn (i, t) => box [p_typ env t,
273 space,
274 string "arg",
275 string (Int.toString i),
276 space,
277 string "=",
278 space,
279 unurlify env t,
280 string ";",
281 newline]) ts),
282 p_enamed env n,
283 string "(",
284 p_list_sep (box [string ",", space])
285 (fn x => x)
286 (string "ctx" :: ListUtil.mapi (fn (i, _) => string ("arg" ^ Int.toString i)) ts),
287 string ");",
288 newline,
289 string "return;",
290 newline,
291 string "}",
292 newline,
293 string "}"]
294 ]
295 230
296 fun p_file env (ds, ps) = 231 fun p_file env (ds, ps) =
297 let 232 let
298 val (pds, env) = ListUtil.foldlMap (fn (d, env) => 233 val (pds, env) = ListUtil.foldlMap (fn (d, env) =>
299 (p_decl env d, 234 (p_decl env d,
300 E.declBinds env d)) 235 E.declBinds env d))
301 env ds 236 env ds
302 val pds' = map (p_page env) ps 237
238 val fields = foldl (fn ((ek, _, _, ts), fields) =>
239 case ek of
240 Core.Link => fields
241 | Core.Action =>
242 case List.last ts of
243 (TRecord i, _) =>
244 let
245 val xts = E.lookupStruct env i
246 val xtsSet = SS.addList (SS.empty, map #1 xts)
247 in
248 foldl (fn ((x, _), fields) =>
249 let
250 val xtsSet' = Option.getOpt (SM.find (fields, x), SS.empty)
251 in
252 SM.insert (fields, x, SS.union (SS.delete (xtsSet, x),
253 xtsSet'))
254 end) fields xts
255 end
256 | _ => raise Fail "CjrPrint: Last argument of action isn't record")
257 SM.empty ps
258
259 val fnums = SM.foldli (fn (x, xs, fnums) =>
260 let
261 val unusable = SS.foldl (fn (x', unusable) =>
262 case SM.find (fnums, x') of
263 NONE => unusable
264 | SOME n => IS.add (unusable, n))
265 IS.empty xs
266
267 fun findAvailable n =
268 if IS.member (unusable, n) then
269 findAvailable (n + 1)
270 else
271 n
272 in
273 SM.insert (fnums, x, findAvailable 0)
274 end)
275 SM.empty fields
276
277 fun makeSwitch (fnums, i) =
278 case SM.foldl (fn (n, NotFound) => Found n
279 | (n, Error) => Error
280 | (n, Found n') => if n = n' then
281 Found n'
282 else
283 Error) NotFound fnums of
284 NotFound => box [string "return",
285 space,
286 string "-1;"]
287 | Found n => box [string "return",
288 space,
289 string (Int.toString n),
290 string ";"]
291 | Error =>
292 let
293 val cmap = SM.foldli (fn (x, n, cmap) =>
294 let
295 val ch = if i < size x then
296 String.sub (x, i)
297 else
298 chr 0
299
300 val fnums = case CM.find (cmap, ch) of
301 NONE => SM.empty
302 | SOME fnums => fnums
303 val fnums = SM.insert (fnums, x, n)
304 in
305 CM.insert (cmap, ch, fnums)
306 end)
307 CM.empty fnums
308
309 val cmap = CM.listItemsi cmap
310 in
311 case cmap of
312 [(_, fnums)] =>
313 box [string "if",
314 space,
315 string "(name[",
316 string (Int.toString i),
317 string "]",
318 space,
319 string "==",
320 space,
321 string "0)",
322 space,
323 string "return",
324 space,
325 string "-1;",
326 newline,
327 makeSwitch (fnums, i+1)]
328 | _ =>
329 box [string "switch",
330 space,
331 string "(name[",
332 string (Int.toString i),
333 string "])",
334 space,
335 string "{",
336 newline,
337 box (map (fn (ch, fnums) =>
338 box [string "case",
339 space,
340 if ch = chr 0 then
341 string "0:"
342 else
343 box [string "'",
344 string (Char.toString ch),
345 string "':"],
346 newline,
347 makeSwitch (fnums, i+1),
348 newline]) cmap),
349 string "default:",
350 newline,
351 string "return",
352 space,
353 string "-1;",
354 newline,
355 string "}"]
356 end
357
358 fun unurlify (t, loc) =
359 case t of
360 TFfi ("Basis", "int") => string "lw_unurlifyInt(&request)"
361 | TFfi ("Basis", "float") => string "lw_unurlifyFloat(&request)"
362 | TFfi ("Basis", "string") => string "lw_unurlifyString(ctx, &request)"
363
364 | TRecord 0 => string "lw_unit_v"
365 | TRecord i =>
366 let
367 val xts = E.lookupStruct env i
368 in
369 box [string "({",
370 newline,
371 box (map (fn (x, t) =>
372 box [p_typ env t,
373 space,
374 string x,
375 space,
376 string "=",
377 space,
378 unurlify t,
379 string ";",
380 newline]) xts),
381 string "struct",
382 space,
383 string "__lws_",
384 string (Int.toString i),
385 space,
386 string "__lw_tmp",
387 space,
388 string "=",
389 space,
390 string "{",
391 space,
392 p_list_sep (box [string ",", space]) (fn (x, _) => string x) xts,
393 space,
394 string "};",
395 newline,
396 string "__lw_tmp;",
397 newline,
398 string "})"]
399 end
400
401 | _ => (ErrorMsg.errorAt loc "Unable to choose a URL decoding function";
402 space)
403
404
405 fun p_page (ek, s, n, ts) =
406 let
407 val (ts, defInputs, inputsVar) =
408 case ek of
409 Core.Link => (ts, string "", string "")
410 | Core.Action =>
411 case List.last ts of
412 (TRecord i, _) =>
413 let
414 val xts = E.lookupStruct env i
415 in
416 (List.drop (ts, 1),
417 box [box (map (fn (x, t) => box [p_typ env t,
418 space,
419 string "lw_input_",
420 string x,
421 string ";",
422 newline]) xts),
423 newline,
424 box (map (fn (x, t) =>
425 let
426 val n = case SM.find (fnums, x) of
427 NONE => raise Fail "CjrPrint: Can't find in fnums"
428 | SOME n => n
429 in
430 box [string "request = lw_get_input(ctx, ",
431 string (Int.toString n),
432 string ");",
433 newline,
434 string "if (request == NULL) {",
435 newline,
436 box [string "printf(\"Missing input ",
437 string x,
438 string "\\n\");",
439 newline,
440 string "exit(1);"],
441 newline,
442 string "}",
443 newline,
444 string "lw_input_",
445 string x,
446 space,
447 string "=",
448 space,
449 unurlify t,
450 string ";",
451 newline]
452 end) xts),
453 string "struct __lws_",
454 string (Int.toString i),
455 space,
456 string "lw_inputs",
457 space,
458 string "= {",
459 newline,
460 box (map (fn (x, _) => box [string "lw_input_",
461 string x,
462 string ",",
463 newline]) xts),
464 string "};",
465 newline],
466 box [string ",",
467 space,
468 string "lw_inputs"])
469 end
470
471 | _ => raise Fail "CjrPrint: Last argument to an action isn't a record"
472 in
473 box [string "if (!strncmp(request, \"",
474 string (String.toString s),
475 string "\", ",
476 string (Int.toString (size s)),
477 string ")) {",
478 newline,
479 string "request += ",
480 string (Int.toString (size s)),
481 string ";",
482 newline,
483 string "if (*request == '/') ++request;",
484 newline,
485 box [string "{",
486 newline,
487 box (ListUtil.mapi (fn (i, t) => box [p_typ env t,
488 space,
489 string "arg",
490 string (Int.toString i),
491 space,
492 string "=",
493 space,
494 unurlify t,
495 string ";",
496 newline]) ts),
497 defInputs,
498 p_enamed env n,
499 string "(",
500 p_list_sep (box [string ",", space])
501 (fn x => x)
502 (string "ctx" :: ListUtil.mapi (fn (i, _) => string ("arg" ^ Int.toString i)) ts),
503 inputsVar,
504 string ");",
505 newline,
506 string "return;",
507 newline,
508 string "}",
509 newline,
510 string "}"]
511 ]
512 end
513
514 val pds' = map p_page ps
303 in 515 in
304 box [string "#include \"lacweb.h\"", 516 box [string "#include <stdio.h>",
517 newline,
518 string "#include <stdlib.h>",
519 newline,
520 newline,
521 string "#include \"lacweb.h\"",
305 newline, 522 newline,
306 newline, 523 newline,
307 p_list_sep newline (fn x => x) pds, 524 p_list_sep newline (fn x => x) pds,
525 newline,
526 string "int lw_inputs_len = ",
527 string (Int.toString (SM.foldl Int.max 0 fnums + 1)),
528 string ";",
529 newline,
530 newline,
531 string "int lw_input_num(char *name) {",
532 newline,
533 string "if",
534 space,
535 string "(name[0]",
536 space,
537 string "==",
538 space,
539 string "0)",
540 space,
541 string "return",
542 space,
543 string "-1;",
544 newline,
545 makeSwitch (fnums, 0),
546 string "}",
547 newline,
308 newline, 548 newline,
309 string "void lw_handle(lw_context ctx, char *request) {", 549 string "void lw_handle(lw_context ctx, char *request) {",
310 newline, 550 newline,
311 p_list_sep newline (fn x => x) pds', 551 p_list_sep newline (fn x => x) pds',
312 newline, 552 newline,