comparison src/cjrize.sml @ 1601:78e0d56b594e

Better error messages when client-side constructs are detected in Cjrize
author Adam Chlipala <adam@chlipala.net>
date Sat, 19 Nov 2011 10:26:19 -0500
parents 36f7d1debb37
children 0577be31a435
comparison
equal deleted inserted replaced
1600:8128fcb2d4a4 1601:78e0d56b594e
235 in 235 in
236 ((L'.PSome (t, p), loc), sm) 236 ((L'.PSome (t, p), loc), sm)
237 end 237 end
238 238
239 fun cifyExp (eAll as (e, loc), sm) = 239 fun cifyExp (eAll as (e, loc), sm) =
240 case e of 240 let
241 L.EPrim p => ((L'.EPrim p, loc), sm) 241 fun fail msg =
242 | L.ERel n => ((L'.ERel n, loc), sm) 242 (ErrorMsg.errorAt loc msg;
243 | L.ENamed n => ((L'.ENamed n, loc), sm) 243 ((L'.EPrim (Prim.String ""), loc), sm))
244 | L.ECon (dk, pc, eo) => 244 in
245 let 245 case e of
246 val (eo, sm) = 246 L.EPrim p => ((L'.EPrim p, loc), sm)
247 case eo of 247 | L.ERel n => ((L'.ERel n, loc), sm)
248 NONE => (NONE, sm) 248 | L.ENamed n => ((L'.ENamed n, loc), sm)
249 | SOME e => 249 | L.ECon (dk, pc, eo) =>
250 let 250 let
251 val (e, sm) = cifyExp (e, sm) 251 val (eo, sm) =
252 in 252 case eo of
253 (SOME e, sm) 253 NONE => (NONE, sm)
254 end 254 | SOME e =>
255 val (pc, sm) = cifyPatCon (pc, sm) 255 let
256 in 256 val (e, sm) = cifyExp (e, sm)
257 ((L'.ECon (dk, pc, eo), loc), sm) 257 in
258 end 258 (SOME e, sm)
259 | L.ENone t => 259 end
260 let 260 val (pc, sm) = cifyPatCon (pc, sm)
261 val (t, sm) = cifyTyp (t, sm) 261 in
262 in 262 ((L'.ECon (dk, pc, eo), loc), sm)
263 ((L'.ENone t, loc), sm) 263 end
264 end 264 | L.ENone t =>
265 | L.ESome (t, e) => 265 let
266 let 266 val (t, sm) = cifyTyp (t, sm)
267 val (t, sm) = cifyTyp (t, sm) 267 in
268 val (e, sm) = cifyExp (e, sm) 268 ((L'.ENone t, loc), sm)
269 in 269 end
270 ((L'.ESome (t, e), loc), sm) 270 | L.ESome (t, e) =>
271 end 271 let
272 | L.EFfi mx => ((L'.EFfi mx, loc), sm) 272 val (t, sm) = cifyTyp (t, sm)
273 | L.EFfiApp (m, x, es) => 273 val (e, sm) = cifyExp (e, sm)
274 let 274 in
275 val (es, sm) = ListUtil.foldlMap cifyExp sm es 275 ((L'.ESome (t, e), loc), sm)
276 in 276 end
277 ((L'.EFfiApp (m, x, es), loc), sm) 277 | L.EFfi mx => ((L'.EFfi mx, loc), sm)
278 end 278 | L.EFfiApp (m, x, es) =>
279 | L.EApp (e1, e2) => 279 let
280 let 280 val (es, sm) = ListUtil.foldlMap cifyExp sm es
281 fun unravel (e, args) = 281 in
282 case e of 282 ((L'.EFfiApp (m, x, es), loc), sm)
283 (L.EApp (e1, e2), _) => unravel (e1, e2 :: args) 283 end
284 | _ => (e, args) 284 | L.EApp (e1, e2) =>
285 285 let
286 val (f, es) = unravel (e1, [e2]) 286 fun unravel (e, args) =
287 287 case e of
288 val (f, sm) = cifyExp (f, sm) 288 (L.EApp (e1, e2), _) => unravel (e1, e2 :: args)
289 val (es, sm) = ListUtil.foldlMap cifyExp sm es 289 | _ => (e, args)
290 in 290
291 ((L'.EApp (f, es), loc), sm) 291 val (f, es) = unravel (e1, [e2])
292 end 292
293 | L.EAbs _ => (ErrorMsg.errorAt loc "Anonymous function remains at code generation"; 293 val (f, sm) = cifyExp (f, sm)
294 Print.prefaces' [("Function", MonoPrint.p_exp MonoEnv.empty eAll)]; 294 val (es, sm) = ListUtil.foldlMap cifyExp sm es
295 (dummye, sm)) 295 in
296 296 ((L'.EApp (f, es), loc), sm)
297 | L.EUnop (s, e1) => 297 end
298 let 298 | L.EAbs _ => (ErrorMsg.errorAt loc "Anonymous function remains at code generation";
299 val (e1, sm) = cifyExp (e1, sm) 299 Print.prefaces' [("Function", MonoPrint.p_exp MonoEnv.empty eAll)];
300 in 300 (dummye, sm))
301 ((L'.EUnop (s, e1), loc), sm) 301
302 end 302 | L.EUnop (s, e1) =>
303 | L.EBinop (_, s, e1, e2) => 303 let
304 let 304 val (e1, sm) = cifyExp (e1, sm)
305 val (e1, sm) = cifyExp (e1, sm) 305 in
306 val (e2, sm) = cifyExp (e2, sm) 306 ((L'.EUnop (s, e1), loc), sm)
307 in 307 end
308 ((L'.EBinop (s, e1, e2), loc), sm) 308 | L.EBinop (_, s, e1, e2) =>
309 end 309 let
310 310 val (e1, sm) = cifyExp (e1, sm)
311 | L.ERecord xes => 311 val (e2, sm) = cifyExp (e2, sm)
312 let 312 in
313 val old_xts = map (fn (x, _, t) => (x, t)) xes 313 ((L'.EBinop (s, e1, e2), loc), sm)
314 314 end
315 val (xets, sm) = ListUtil.foldlMap (fn ((x, e, t), sm) => 315
316 let 316 | L.ERecord xes =>
317 val (e, sm) = cifyExp (e, sm) 317 let
318 val (t, sm) = cifyTyp (t, sm) 318 val old_xts = map (fn (x, _, t) => (x, t)) xes
319 in 319
320 ((x, e, t), sm) 320 val (xets, sm) = ListUtil.foldlMap (fn ((x, e, t), sm) =>
321 end) 321 let
322 sm xes 322 val (e, sm) = cifyExp (e, sm)
323 323 val (t, sm) = cifyTyp (t, sm)
324 val (sm, si) = Sm.find (sm, old_xts, map (fn (x, _, t) => (x, t)) xets) 324 in
325 325 ((x, e, t), sm)
326 val xes = map (fn (x, e, _) => (x, e)) xets 326 end)
327 val xes = ListMergeSort.sort (fn ((x1, _), (x2, _)) => String.compare (x1, x2) = GREATER) xes 327 sm xes
328 in 328
329 ((L'.ERecord (si, xes), loc), sm) 329 val (sm, si) = Sm.find (sm, old_xts, map (fn (x, _, t) => (x, t)) xets)
330 end 330
331 | L.EField (e, x) => 331 val xes = map (fn (x, e, _) => (x, e)) xets
332 let 332 val xes = ListMergeSort.sort (fn ((x1, _), (x2, _)) => String.compare (x1, x2) = GREATER) xes
333 val (e, sm) = cifyExp (e, sm) 333 in
334 in 334 ((L'.ERecord (si, xes), loc), sm)
335 ((L'.EField (e, x), loc), sm) 335 end
336 end 336 | L.EField (e, x) =>
337 337 let
338 | L.ECase (e, pes, {disc, result}) => 338 val (e, sm) = cifyExp (e, sm)
339 let 339 in
340 ((L'.EField (e, x), loc), sm)
341 end
342
343 | L.ECase (e, pes, {disc, result}) =>
344 let
340 val (e, sm) = cifyExp (e, sm) 345 val (e, sm) = cifyExp (e, sm)
341 val (pes, sm) = ListUtil.foldlMap 346 val (pes, sm) = ListUtil.foldlMap
342 (fn ((p, e), sm) => 347 (fn ((p, e), sm) =>
343 let 348 let
344 val (e, sm) = cifyExp (e, sm) 349 val (e, sm) = cifyExp (e, sm)
350 val (result, sm) = cifyTyp (result, sm) 355 val (result, sm) = cifyTyp (result, sm)
351 in 356 in
352 ((L'.ECase (e, pes, {disc = disc, result = result}), loc), sm) 357 ((L'.ECase (e, pes, {disc = disc, result = result}), loc), sm)
353 end 358 end
354 359
355 | L.EError (e, t) => 360 | L.EError (e, t) =>
356 let 361 let
357 val (e, sm) = cifyExp (e, sm) 362 val (e, sm) = cifyExp (e, sm)
358 val (t, sm) = cifyTyp (t, sm) 363 val (t, sm) = cifyTyp (t, sm)
359 in 364 in
360 ((L'.EError (e, t), loc), sm) 365 ((L'.EError (e, t), loc), sm)
361 end 366 end
362 | L.EReturnBlob {blob, mimeType, t} => 367 | L.EReturnBlob {blob, mimeType, t} =>
363 let 368 let
364 val (blob, sm) = cifyExp (blob, sm) 369 val (blob, sm) = cifyExp (blob, sm)
365 val (mimeType, sm) = cifyExp (mimeType, sm) 370 val (mimeType, sm) = cifyExp (mimeType, sm)
366 val (t, sm) = cifyTyp (t, sm) 371 val (t, sm) = cifyTyp (t, sm)
367 in 372 in
368 ((L'.EReturnBlob {blob = blob, mimeType = mimeType, t = t}, loc), sm) 373 ((L'.EReturnBlob {blob = blob, mimeType = mimeType, t = t}, loc), sm)
369 end 374 end
370 | L.ERedirect (e, t) => 375 | L.ERedirect (e, t) =>
371 let 376 let
372 val (e, sm) = cifyExp (e, sm) 377 val (e, sm) = cifyExp (e, sm)
373 val (t, sm) = cifyTyp (t, sm) 378 val (t, sm) = cifyTyp (t, sm)
374 in 379 in
375 ((L'.ERedirect (e, t), loc), sm) 380 ((L'.ERedirect (e, t), loc), sm)
376 end 381 end
377 382
378 | L.EStrcat (e1, e2) => 383 | L.EStrcat (e1, e2) =>
379 let 384 let
380 val (e1, sm) = cifyExp (e1, sm) 385 val (e1, sm) = cifyExp (e1, sm)
381 val (e2, sm) = cifyExp (e2, sm) 386 val (e2, sm) = cifyExp (e2, sm)
382 in 387 in
383 ((L'.EFfiApp ("Basis", "strcat", [e1, e2]), loc), sm) 388 ((L'.EFfiApp ("Basis", "strcat", [e1, e2]), loc), sm)
384 end 389 end
385 390
386 | L.EWrite e => 391 | L.EWrite e =>
387 let 392 let
388 val (e, sm) = cifyExp (e, sm) 393 val (e, sm) = cifyExp (e, sm)
389 in 394 in
390 ((L'.EWrite e, loc), sm) 395 ((L'.EWrite e, loc), sm)
391 end 396 end
392 397
393 | L.ESeq (e1, e2) => 398 | L.ESeq (e1, e2) =>
394 let 399 let
395 val (e1, sm) = cifyExp (e1, sm) 400 val (e1, sm) = cifyExp (e1, sm)
396 val (e2, sm) = cifyExp (e2, sm) 401 val (e2, sm) = cifyExp (e2, sm)
397 in 402 in
398 ((L'.ESeq (e1, e2), loc), sm) 403 ((L'.ESeq (e1, e2), loc), sm)
399 end 404 end
400 405
401 | L.ELet (x, t, e1, e2) => 406 | L.ELet (x, t, e1, e2) =>
402 let 407 let
403 val (t, sm) = cifyTyp (t, sm) 408 val (t, sm) = cifyTyp (t, sm)
404 val (e1, sm) = cifyExp (e1, sm) 409 val (e1, sm) = cifyExp (e1, sm)
405 val (e2, sm) = cifyExp (e2, sm) 410 val (e2, sm) = cifyExp (e2, sm)
406 in 411 in
407 ((L'.ELet (x, t, e1, e2), loc), sm) 412 ((L'.ELet (x, t, e1, e2), loc), sm)
408 end 413 end
409 414
410 | L.EClosure _ => (ErrorMsg.errorAt loc "Nested closure remains in code generation"; 415 | L.EClosure _ => (ErrorMsg.errorAt loc "Nested closure remains in code generation";
411 (dummye, sm)) 416 (dummye, sm))
412 417
413 | L.EQuery {exps, tables, state, query, body, initial} => 418 | L.EQuery {exps, tables, state, query, body, initial} =>
414 let 419 let
415 val (exps', sm) = ListUtil.foldlMap (fn ((x, t), sm) => 420 val (exps', sm) = ListUtil.foldlMap (fn ((x, t), sm) =>
416 let
417 val (t, sm) = cifyTyp (t, sm)
418 in
419 ((x, t), sm)
420 end) sm exps
421 val (tables', sm) = ListUtil.foldlMap (fn ((x, xts), sm) =>
422 let
423 val (xts, sm) = ListUtil.foldlMap
424 (fn ((x, t), sm) =>
425 let
426 val (t, sm) = cifyTyp (t, sm)
427 in
428 ((x, t), sm)
429 end) sm xts
430 in
431 ((x, xts), sm)
432 end) sm tables
433
434 val row = exps @ map (fn (x, xts) => (x, (L.TRecord xts, loc))) tables
435 val row = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) row
436
437 val (tableRows, sm) = ListUtil.foldlMap (fn (((x, xts), (_, xts')), sm) =>
438 let 421 let
439 val (sm, rnum) = Sm.find (sm, xts, xts') 422 val (t, sm) = cifyTyp (t, sm)
440 in 423 in
441 ((x, rnum), sm) 424 ((x, t), sm)
442 end) 425 end) sm exps
443 sm (ListPair.zip (tables, tables')) 426 val (tables', sm) = ListUtil.foldlMap (fn ((x, xts), sm) =>
444 val row' = exps' @ map (fn (x, n) => (x, (L'.TRecord n, loc))) tableRows 427 let
445 val row' = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) row' 428 val (xts, sm) = ListUtil.foldlMap
446 429 (fn ((x, t), sm) =>
447 val (sm, rnum) = Sm.find (sm, row, row') 430 let
448 431 val (t, sm) = cifyTyp (t, sm)
449 val (state, sm) = cifyTyp (state, sm) 432 in
450 val (query, sm) = cifyExp (query, sm) 433 ((x, t), sm)
451 val (body, sm) = cifyExp (body, sm) 434 end) sm xts
452 val (initial, sm) = cifyExp (initial, sm) 435 in
453 in 436 ((x, xts), sm)
454 ((L'.EQuery {exps = exps', tables = tables', rnum = rnum, state = state, 437 end) sm tables
455 query = query, body = body, initial = initial, prepared = NONE}, loc), sm) 438
456 end 439 val row = exps @ map (fn (x, xts) => (x, (L.TRecord xts, loc))) tables
457 440 val row = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) row
458 | L.EDml (e, mode) => 441
459 let 442 val (tableRows, sm) = ListUtil.foldlMap (fn (((x, xts), (_, xts')), sm) =>
460 val (e, sm) = cifyExp (e, sm) 443 let
461 in 444 val (sm, rnum) = Sm.find (sm, xts, xts')
462 ((L'.EDml {dml = e, prepared = NONE, mode = mode}, loc), sm) 445 in
463 end 446 ((x, rnum), sm)
464 447 end)
465 | L.ENextval e => 448 sm (ListPair.zip (tables, tables'))
466 let 449 val row' = exps' @ map (fn (x, n) => (x, (L'.TRecord n, loc))) tableRows
467 val (e, sm) = cifyExp (e, sm) 450 val row' = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) row'
468 in 451
469 ((L'.ENextval {seq = e, prepared = NONE}, loc), sm) 452 val (sm, rnum) = Sm.find (sm, row, row')
470 end 453
471 | L.ESetval (e1, e2) => 454 val (state, sm) = cifyTyp (state, sm)
472 let 455 val (query, sm) = cifyExp (query, sm)
473 val (e1, sm) = cifyExp (e1, sm) 456 val (body, sm) = cifyExp (body, sm)
474 val (e2, sm) = cifyExp (e2, sm) 457 val (initial, sm) = cifyExp (initial, sm)
475 in 458 in
476 ((L'.ESetval {seq = e1, count = e2}, loc), sm) 459 ((L'.EQuery {exps = exps', tables = tables', rnum = rnum, state = state,
477 end 460 query = query, body = body, initial = initial, prepared = NONE}, loc), sm)
478 461 end
479 | L.EUnurlify (e, t, b) => 462
480 let 463 | L.EDml (e, mode) =>
481 val (e, sm) = cifyExp (e, sm) 464 let
482 val (t, sm) = cifyTyp (t, sm) 465 val (e, sm) = cifyExp (e, sm)
483 in 466 in
484 ((L'.EUnurlify (e, t, b), loc), sm) 467 ((L'.EDml {dml = e, prepared = NONE, mode = mode}, loc), sm)
485 end 468 end
486 469
487 | L.EJavaScript _ => raise Fail "Cjrize: EJavaScript remains" 470 | L.ENextval e =>
488 471 let
489 | L.ESignalReturn _ => raise Fail "Cjrize: ESignalReturn remains" 472 val (e, sm) = cifyExp (e, sm)
490 | L.ESignalBind _ => raise Fail "Cjrize: ESignalBind remains" 473 in
491 | L.ESignalSource _ => raise Fail "Cjrize: ESignalSource remains" 474 ((L'.ENextval {seq = e, prepared = NONE}, loc), sm)
492 475 end
493 | L.EServerCall _ => raise Fail "Cjrize EServerCall" 476 | L.ESetval (e1, e2) =>
494 | L.ERecv _ => raise Fail "Cjrize ERecv" 477 let
495 | L.ESleep _ => raise Fail "Cjrize ESleep" 478 val (e1, sm) = cifyExp (e1, sm)
496 | L.ESpawn _ => raise Fail "Cjrize ESpawn" 479 val (e2, sm) = cifyExp (e2, sm)
480 in
481 ((L'.ESetval {seq = e1, count = e2}, loc), sm)
482 end
483
484 | L.EUnurlify (e, t, b) =>
485 let
486 val (e, sm) = cifyExp (e, sm)
487 val (t, sm) = cifyTyp (t, sm)
488 in
489 ((L'.EUnurlify (e, t, b), loc), sm)
490 end
491
492 | L.EJavaScript _ => fail "Uncompilable JavaScript remains"
493
494 | L.ESignalReturn _ => fail "Signal monad 'return' remains in server-side code"
495 | L.ESignalBind _ => fail "Signal monad 'bind' remains in server-side code"
496 | L.ESignalSource _ => fail "Signal monad 'source' remains in server-side code"
497
498 | L.EServerCall _ => fail "RPC in server-side code"
499 | L.ERecv _ => fail "Message receive in server-side code"
500 | L.ESleep _ => fail "Sleep in server-side code"
501 | L.ESpawn _ => fail "Thread spawn in server-side code"
502 end
497 503
498 fun cifyDecl ((d, loc), sm) = 504 fun cifyDecl ((d, loc), sm) =
499 case d of 505 case d of
500 L.DDatatype dts => 506 L.DDatatype dts =>
501 let 507 let