Mercurial > repos > icfp2014
comparison code/gqc.tp @ 58:d35601d47db1
Implement if:else in gqc
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 27 Jul 2014 20:03:34 -0700 |
parents | fde898a3cbbe |
children | 2a5d7308e1df |
comparison
equal
deleted
inserted
replaced
57:a3e4d2833301 | 58:d35601d47db1 |
---|---|
363 } else: { | 363 } else: { |
364 error: "Condition parameter to while:do must be a comparison operator expression" | 364 error: "Condition parameter to while:do must be a comparison operator expression" |
365 } | 365 } |
366 } | 366 } |
367 | 367 |
368 _funHandlers set: "if:else" :args syms { | |
369 cond <- (args value) | |
370 trueBody <- ((args tail) value) expressions | |
371 falseBody <- (((args tail) tail) value) expressions | |
372 | |
373 if: (cond nodeType) = (ast binary) { | |
374 trueLbl <- prog makeLabel: "true" | |
375 falseLbl <- prog makeLabel: "false" | |
376 endLbl <- prog makeLabel: "end" | |
377 | |
378 saveTempRegs <- _tempRegs | |
379 l <- compileExpr: (cond left) syms: syms | |
380 r <- compileExpr: (cond right) syms: syms | |
381 _tempRegs <- saveTempRegs | |
382 | |
383 ok <- true | |
384 | |
385 if: (cond op) = ">=" { | |
386 prog add: (inst: "JLT" #[ | |
387 falseLbl | |
388 l | |
389 r | |
390 ]) | |
391 } else: { | |
392 if: (cond op) = "<=" { | |
393 prog add: (inst: "JGT" #[ | |
394 falseLbl | |
395 l | |
396 r | |
397 ]) | |
398 } else: { | |
399 if: (cond op) = "!=" { | |
400 prog add: (inst: "JEQ" #[ | |
401 falseLbl | |
402 l | |
403 r | |
404 ]) | |
405 } else: { | |
406 if: (cond op) = ">" { | |
407 prog add: (inst: "JGT" #[ | |
408 trueLbl | |
409 l | |
410 r | |
411 ]) | |
412 prog add: (inst: "MOV" #[ | |
413 reg: 8 | |
414 falseLbl | |
415 ]) | |
416 } else: { | |
417 if: (cond op) = "<" { | |
418 prog add: (inst: "JLT" #[ | |
419 trueLbl | |
420 l | |
421 r | |
422 ]) | |
423 prog add: (inst: "MOV" #[ | |
424 reg: 8 | |
425 falseLbl | |
426 ]) | |
427 } else: { | |
428 bodyLbl <- prog makeLabel: "loop_body" | |
429 if: (cond op) = "=" { | |
430 prog add: (inst: "JEQ" #[ | |
431 trueLbl | |
432 l | |
433 r | |
434 ]) | |
435 prog add: (inst: "MOV" #[ | |
436 reg: 8 | |
437 falseLbl | |
438 ]) | |
439 } else: { | |
440 ok <- false | |
441 } | |
442 } | |
443 } | |
444 } | |
445 } | |
446 } | |
447 if: ok { | |
448 prog setLabel: trueLbl | |
449 //TODO: do 2 passes for labels to allow forward references | |
450 foreach: trueBody :idx expr { | |
451 if: (expr nodeType) = (ast sym) { | |
452 //allow using bare symbols to define labels | |
453 lbl <- prog makeLabel: (expr name) | |
454 prog setLabel: lbl | |
455 syms define: (expr name) lbl | |
456 } else: { | |
457 saveTempRegsExpr <- _tempRegs | |
458 v <- compileExpr: expr syms: syms | |
459 _tempRegs <- saveTempRegsExpr | |
460 } | |
461 } | |
462 prog add: (inst: "MOV" #[ | |
463 reg: 8 | |
464 endLbl | |
465 ]) | |
466 prog setLabel: falseLbl | |
467 //TODO: do 2 passes for labels to allow forward references | |
468 foreach: falseBody :idx expr { | |
469 if: (expr nodeType) = (ast sym) { | |
470 //allow using bare symbols to define labels | |
471 lbl <- prog makeLabel: (expr name) | |
472 prog setLabel: lbl | |
473 syms define: (expr name) lbl | |
474 } else: { | |
475 saveTempRegsExpr <- _tempRegs | |
476 v <- compileExpr: expr syms: syms | |
477 _tempRegs <- saveTempRegsExpr | |
478 } | |
479 } | |
480 prog setLabel: endLbl | |
481 } else: { | |
482 error: "Condition parameter to if:else must be a comparison operator expression" | |
483 } | |
484 } else: { | |
485 error: "Condition parameter to if:else must be a comparison operator expression" | |
486 } | |
487 } | |
488 | |
368 _exprHandlers set: (ast call) :expr syms { | 489 _exprHandlers set: (ast call) :expr syms { |
369 tc <- (expr tocall) | 490 tc <- (expr tocall) |
370 if: (tc nodeType) = (ast sym) { | 491 if: (tc nodeType) = (ast sym) { |
371 _funHandlers ifget: (tc name) :handler { | 492 _funHandlers ifget: (tc name) :handler { |
372 handler: (expr args) syms | 493 handler: (expr args) syms |