Mercurial > repos > icfp2014
comparison code/gcc.tp @ 49:ec87d53603dd
gcc simulator now works correctly at least for the subset used by ghc.lm and has some primitive debugging facilities
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 27 Jul 2014 13:36:56 -0700 |
parents | 6d2cbad5fca9 |
children |
comparison
equal
deleted
inserted
replaced
48:8b6f6e2cbf38 | 49:ec87d53603dd |
---|---|
1 #{ | 1 #{ |
2 new <- :code { | 2 getTag <- :val { |
3 if: (val isInteger?) { | |
4 "INTEGER" | |
5 } else: { | |
6 val tag | |
7 } | |
8 } | |
9 | |
10 ifError:else <- :val iferr :else { | |
11 if: (val isInteger?) { | |
12 else: | |
13 } else: { | |
14 if: (val isError?) { | |
15 iferr: | |
16 } else: { | |
17 else: | |
18 } | |
19 } | |
20 } | |
21 | |
22 new <- :rawCode { | |
3 consUsage <- 0 | 23 consUsage <- 0 |
4 dataStack <- [] | 24 dataStack <- [] |
5 controlStack <- 0 | 25 controlStack <- 0 |
6 stackSize <- 0 | 26 stackSize <- 0 |
7 pc <- 0 | 27 _pc <- 0 |
8 | 28 |
9 error <- :_msg { | 29 error <- :_msg { |
10 #{ | 30 #{ |
11 msg <- { _msg } | 31 msg <- { _msg } |
12 isInteger? <- { false } | 32 isInteger? <- { false } |
15 isEnvironment? <- { false } | 35 isEnvironment? <- { false } |
16 isCons? <- { false } | 36 isCons? <- { false } |
17 isJoin? <- { false } | 37 isJoin? <- { false } |
18 isStop? <- { false } | 38 isStop? <- { false } |
19 tag <- { "ERROR" } | 39 tag <- { "ERROR" } |
40 string <- { _msg } | |
20 } | 41 } |
21 } | 42 } |
22 _dummy <- #{ | 43 _dummy <- #{ |
23 isInteger? <- { false } | 44 isInteger? <- { false } |
24 isError? <- { false } | 45 isError? <- { false } |
26 isEnvironment? <- { false } | 47 isEnvironment? <- { false } |
27 isCons? <- { false } | 48 isCons? <- { false } |
28 isJoin? <- { false } | 49 isJoin? <- { false } |
29 isStop? <- { false } | 50 isStop? <- { false } |
30 tag <- { "DUMMY" } | 51 tag <- { "DUMMY" } |
31 } | 52 string <- { tag } |
32 | |
33 getTag <- :val { | |
34 if: (val isInteger?) { | |
35 "INTEGER" | |
36 } else: { | |
37 val tag | |
38 } | |
39 } | 53 } |
40 | 54 |
41 push <- :val { | 55 push <- :val { |
42 dataStack <- val | dataStack | 56 dataStack <- val | dataStack |
43 stackSize <- stackSize + 1 | 57 stackSize <- stackSize + 1 |
62 error: "invalid environment" | 76 error: "invalid environment" |
63 } | 77 } |
64 rapLoad <- { | 78 rapLoad <- { |
65 error: "invalid environment" | 79 error: "invalid environment" |
66 } | 80 } |
81 arr <- { #[] } | |
67 isError? <- { false } | 82 isError? <- { false } |
68 isEnvironment? <- { true } | 83 isEnvironment? <- { true } |
69 isJoin? <- { false } | 84 isJoin? <- { false } |
70 isReturn? <- { false } | 85 isReturn? <- { false } |
71 isStop? <- { false } | 86 isStop? <- { false } |
72 tag <- { "TOPENV" } | 87 tag <- { "TOPENV" } |
88 string <- { tag } | |
73 } | 89 } |
74 | 90 |
75 cons <- :_car _cdr { | 91 cons <- :_car _cdr { |
76 consUsage <- consUsage + 1 | 92 consUsage <- consUsage + 1 |
77 #{ | 93 #{ |
82 isClosure? <- { false } | 98 isClosure? <- { false } |
83 isEnvironment? <- { false } | 99 isEnvironment? <- { false } |
84 isCons? <- { true } | 100 isCons? <- { true } |
85 isJoin? <- { false } | 101 isJoin? <- { false } |
86 tag <- { "CONS" } | 102 tag <- { "CONS" } |
103 string <- { "(" . _car . ", " . _cdr . ")" } | |
87 } | 104 } |
88 } | 105 } |
89 | 106 |
90 | 107 |
91 env:dummy? <- :_size _parent :_dummy? { | 108 env:dummy? <- :_size _parent :_dummy? { |
184 isEnvironment? <- { true } | 201 isEnvironment? <- { true } |
185 isJoin? <- { false } | 202 isJoin? <- { false } |
186 isReturn? <- { false } | 203 isReturn? <- { false } |
187 isStop? <- { false } | 204 isStop? <- { false } |
188 tag <- { "ENVIRONMENT" } | 205 tag <- { "ENVIRONMENT" } |
206 string <- { tag } | |
207 arr <- { _arr } | |
189 } | 208 } |
190 } | 209 } |
191 } | 210 } |
192 | 211 |
193 | 212 |
201 isClosure? <- { true } | 220 isClosure? <- { true } |
202 isEnvironment? <- { false } | 221 isEnvironment? <- { false } |
203 isCons? <- { false } | 222 isCons? <- { false } |
204 isJoin? <- { false } | 223 isJoin? <- { false } |
205 tag <- { "CLOSURE" } | 224 tag <- { "CLOSURE" } |
206 } | 225 string <- { "{" . _address . ", " . _env . "}" } |
207 } | 226 } |
208 | 227 } |
209 join <- :_address { | 228 |
229 joinVal <- :_address { | |
210 #{ | 230 #{ |
211 address <- { _address } | 231 address <- { _address } |
212 isError? <- { false } | 232 isError? <- { false } |
213 isEnvironment? <- { false } | 233 isEnvironment? <- { false } |
214 isJoin? <- { true } | 234 isJoin? <- { true } |
215 isReturn? <- { false } | 235 isReturn? <- { false } |
216 isStop? <- { false } | 236 isStop? <- { false } |
217 tag <- { "JOIN" } | 237 tag <- { "JOIN" } |
238 string <- { tag } | |
218 } | 239 } |
219 } | 240 } |
220 return <- :_address { | 241 return <- :_address { |
221 #{ | 242 #{ |
222 address <- { _address } | 243 address <- { _address } |
224 isEnvironment? <- { false } | 245 isEnvironment? <- { false } |
225 isJoin? <- { false } | 246 isJoin? <- { false } |
226 isReturn? <- { true } | 247 isReturn? <- { true } |
227 isStop? <- { false } | 248 isStop? <- { false } |
228 tag <- { "RETURN" } | 249 tag <- { "RETURN" } |
250 string <- { tag . " " . _address } | |
229 } | 251 } |
230 } | 252 } |
231 stop <- #{ | 253 stop <- #{ |
232 isError? <- { false } | 254 isError? <- { false } |
233 isEnvironment? <- { false } | 255 isEnvironment? <- { false } |
234 isJoin? <- { false } | 256 isJoin? <- { false } |
235 isReturn? <- { false } | 257 isReturn? <- { false } |
236 isStop? <- { true } | 258 isStop? <- { true } |
237 tag <- { "STOP" } | 259 tag <- { "STOP" } |
260 string <- { tag } | |
238 } | 261 } |
239 | 262 |
240 _instConstructors <- dict hash | 263 _instConstructors <- dict hash |
241 _instConstructors set: "LDC" :args { | 264 _instConstructors set: "LDC" :args { |
242 _const <- args get: 0 | 265 _const <- args get: 0 |
279 b <- pop: | 302 b <- pop: |
280 if: (b isInteger?) { | 303 if: (b isInteger?) { |
281 push: op | 304 push: op |
282 _dummy | 305 _dummy |
283 } else: { | 306 } else: { |
284 if: (b isError?) { | 307 if: (b isError?) { |
285 b | 308 b |
286 } else: { | 309 } else: { |
287 error: "Got wrong type for left param of " . name . " instruction" | 310 error: "Got wrong type for left param of " . name . " instruction" |
288 } | 311 } |
289 } | 312 } |
379 _t <- args get: 0 | 402 _t <- args get: 0 |
380 _f <- args get: 1 | 403 _f <- args get: 1 |
381 { | 404 { |
382 val <- pop: | 405 val <- pop: |
383 if: (val isInteger?) { | 406 if: (val isInteger?) { |
384 controlStack <- cons: (join: pc) controlStack | 407 controlStack <- cons: (joinVal: _pc) controlStack |
385 pc <- if: (val != 0) { _t } else: { _f } | 408 _pc <- if: (val != 0) { _t } else: { _f } |
386 _dummy | 409 _dummy |
387 } else: { | 410 } else: { |
388 if: (val isError?) { | 411 if: (val isError?) { |
389 val | 412 val |
390 } else: { | 413 } else: { |
397 _t <- args get: 0 | 420 _t <- args get: 0 |
398 _f <- args get: 1 | 421 _f <- args get: 1 |
399 { | 422 { |
400 val <- pop: | 423 val <- pop: |
401 if: (val isInteger?) { | 424 if: (val isInteger?) { |
402 pc <- if: (val != 0) { _t } else: { _f } | 425 _pc <- if: (val != 0) { _t } else: { _f } |
403 _dummy | 426 _dummy |
404 } else: { | 427 } else: { |
405 if: (val isError?) { | 428 if: (val isError?) { |
406 val | 429 val |
407 } else: { | 430 } else: { |
416 error: "JOIN tried to pull value from empty control stack" | 439 error: "JOIN tried to pull value from empty control stack" |
417 } else: { | 440 } else: { |
418 val <- controlStack car | 441 val <- controlStack car |
419 controlStack <- controlStack cdr | 442 controlStack <- controlStack cdr |
420 if: (val isJoin?) { | 443 if: (val isJoin?) { |
421 pc <- val address | 444 _pc <- val address |
422 _dummy | 445 _dummy |
423 } else: { | 446 } else: { |
424 error: "JOIN expects JOIN cell, got " . (val tag) . " instead" | 447 error: "JOIN expects JOIN cell, got " . (val tag) . " instead" |
425 } | 448 } |
426 } | 449 } |
446 if: (val isClosure?) { | 469 if: (val isClosure?) { |
447 frame <- env: _envSize (val env) dummy?: false | 470 frame <- env: _envSize (val env) dummy?: false |
448 if: (frame isError?) { | 471 if: (frame isError?) { |
449 frame | 472 frame |
450 } else: { | 473 } else: { |
451 controlStack <- cons: (return: pc+1) (cons: _curEnv controlStack) | 474 controlStack <- cons: (return: _pc) (cons: _curEnv controlStack) |
452 _curEnv <- frame | 475 _curEnv <- frame |
453 pc <- val address | 476 _pc <- val address |
454 _dummy | 477 _dummy |
455 } | 478 } |
456 } else: { | 479 } else: { |
457 error: "AP expects CLOSURE, got " . (val tag) . " instead" | 480 error: "AP expects CLOSURE, got " . (val tag) . " instead" |
458 } | 481 } |
474 frame <- env: _envSize (val env) dummy?: false | 497 frame <- env: _envSize (val env) dummy?: false |
475 if: (frame isError?) { | 498 if: (frame isError?) { |
476 frame | 499 frame |
477 } else: { | 500 } else: { |
478 _curEnv <- frame | 501 _curEnv <- frame |
479 pc <- val address | 502 _pc <- val address |
480 _dummy | 503 _dummy |
481 } | 504 } |
482 } else: { | 505 } else: { |
483 error: "TAP expects CLOSURE, got " . (val tag) . " instead" | 506 error: "TAP expects CLOSURE, got " . (val tag) . " instead" |
484 } | 507 } |
494 val <- controlStack car | 517 val <- controlStack car |
495 controlStack <- controlStack cdr | 518 controlStack <- controlStack cdr |
496 if: (val isReturn?) { | 519 if: (val isReturn?) { |
497 _curEnv <- controlStack car | 520 _curEnv <- controlStack car |
498 controlStack <- controlStack cdr | 521 controlStack <- controlStack cdr |
499 pc <- val address | 522 _pc <- val address |
500 _dummy | 523 _dummy |
501 } else: { | 524 } else: { |
502 if: (val isStop?) { | 525 if: (val isStop?) { |
503 val | 526 val |
504 } else: { | 527 } else: { |
534 res <- _curEnv rapLoad: _envSize | 557 res <- _curEnv rapLoad: _envSize |
535 if: (not: (res isError?)) { | 558 if: (not: (res isError?)) { |
536 if: (val env) != _curEnv { | 559 if: (val env) != _curEnv { |
537 res <- error: "CLOSURE environment must equal current environment for RAP" | 560 res <- error: "CLOSURE environment must equal current environment for RAP" |
538 } else: { | 561 } else: { |
539 controlStack <- cons: (return: pc+1) (cons: (_curEnv parent) controlStack) | 562 controlStack <- cons: (return: _pc) (cons: (_curEnv parent) controlStack) |
540 pc <- val address | 563 _pc <- val address |
541 } | 564 } |
542 } | 565 } |
543 res | 566 res |
544 } else: { | 567 } else: { |
545 error: "RAP expects CLOSURE, got " . (val tag) . " instead" | 568 error: "RAP expects CLOSURE, got " . (val tag) . " instead" |
562 res <- _curEnv rapLoad: _envSize | 585 res <- _curEnv rapLoad: _envSize |
563 if: (not: (res isError?)) { | 586 if: (not: (res isError?)) { |
564 if: (val env) != _curEnv { | 587 if: (val env) != _curEnv { |
565 res <- error: "CLOSURE environment must equal current environment for RAP" | 588 res <- error: "CLOSURE environment must equal current environment for RAP" |
566 } else: { | 589 } else: { |
567 pc <- val address | 590 _pc <- val address |
568 } | 591 } |
569 } | 592 } |
570 res | 593 res |
571 } else: { | 594 } else: { |
572 error: "RAP expects CLOSURE, got " . (val tag) . " instead" | 595 error: "RAP expects CLOSURE, got " . (val tag) . " instead" |
595 { | 618 { |
596 _dummy | 619 _dummy |
597 } | 620 } |
598 } | 621 } |
599 | 622 |
600 code <- code map: :i { | 623 code <- rawCode map: :i { |
601 foobar <- _instConstructors get: (i inst) else: { { stop } } | 624 foobar <- _instConstructors get: (i inst) else: { { stop } } |
602 foobar: (i args) | 625 foobar: (i args) |
603 } | 626 } |
604 | 627 |
628 | |
629 _stepMode? <- false | |
630 _lastCommand <- "" | |
631 _breakFun <- :cpu { | |
632 i <- (rawCode get: (cpu pc)) | |
633 print: (string: (cpu pc)) . ": " . (i inst) . " " . ((i args) join: " ") . "\n" | |
634 | |
635 command <- "" | |
636 while: { command != "c" && command != "s"} do: { | |
637 command <- ((file stdin) nextLine) trim | |
638 if: command = "" { | |
639 command <- _lastCommand | |
640 } else: { | |
641 _lastCommand <- command | |
642 } | |
643 if: command = "d" { | |
644 print: "Data Stack:\n" | |
645 ds <- cpu dstack | |
646 while: { not: (ds empty?) } do: { | |
647 print: "\t" . (ds value) . "\n" | |
648 ds <- ds tail | |
649 } | |
650 } | |
651 if: command = "b" { | |
652 print: "Control Stack:\n" | |
653 cs <- cpu cstack | |
654 while: { not: (cs isInteger?) } do: { | |
655 print: "\t" . (cs car) . "\n" | |
656 cs <- cs cdr | |
657 } | |
658 } | |
659 if: command = "e" { | |
660 print: "Environment:\n" | |
661 env <- cpu environment | |
662 foreach: ((cpu environment) arr) :idx val { | |
663 print: "\t" . idx . ": " . val . "\n" | |
664 } | |
665 } | |
666 } | |
667 if: command = "c" { | |
668 cpu runMode | |
669 } | |
670 } | |
671 _cycles <- 0 | |
605 #{ | 672 #{ |
606 limit <- 3072 * 1000 | 673 limit <- 3072 * 1000 |
674 stepMode <- { | |
675 _stepMode? <- true | |
676 self | |
677 } | |
678 runMode <- { | |
679 _stepMode? <- false | |
680 self | |
681 } | |
682 breakFun <- _breakFun | |
683 | |
684 pc <- { _pc } | |
685 dstack <- { dataStack } | |
686 cstack <- { controlStack } | |
687 environment <- { _curEnv } | |
688 cycles <- { _cycles } | |
689 | |
607 run <- { | 690 run <- { |
608 cycles <- 0 | 691 _cycles <- 0 |
692 controlStack <- cons: stop 0 | |
609 status <- _dummy | 693 status <- _dummy |
610 while: { (not: (status isError?)) && (not: (status isStop?)) } do: { | 694 while: { (not: (status isError?)) && (not: (status isStop?)) } do: { |
611 oldpc <- pc | 695 if: _stepMode? { |
612 if: (cycles >= limit) { | 696 break <- breakFun |
697 break: self | |
698 } | |
699 if: (_cycles >= limit) { | |
613 status <- error: "cycle limit of " . limit . " exceeded" | 700 status <- error: "cycle limit of " . limit . " exceeded" |
614 } else: { | 701 } else: { |
615 if: (pc >= (code length)) { | 702 if: (_pc >= (code length)) { |
616 status <- error: "PC walked off end of program" | 703 status <- error: "PC walked off end of program" |
617 } else: { | 704 } else: { |
618 inst <- code get: pc | 705 inst <- code get: _pc |
619 pc <- -1 | 706 _pc <- _pc + 1 |
620 status <- inst: | 707 status <- inst: |
621 if: pc = -1 { | 708 _cycles <- _cycles + 1 |
622 pc <- oldpc + 1 | 709 } |
623 } | 710 } |
624 cycles <- cycles + 1 | 711 } |
625 } | |
626 } | |
627 } | |
628 print: "Status: " . (status tag) . "\n" | |
629 if: (status isStop?) { | 712 if: (status isStop?) { |
630 if: (dataStack empty?) { | 713 if: (dataStack empty?) { |
631 _dummy | 714 _dummy |
632 } else: { | 715 } else: { |
633 pop: | 716 pop: |
664 if: (args length) > 1 { | 747 if: (args length) > 1 { |
665 f <- file open: (args get: 1) | 748 f <- file open: (args get: 1) |
666 if: (f fd) >= 0 { | 749 if: (f fd) >= 0 { |
667 code <- parseFile: f | 750 code <- parseFile: f |
668 cpu <- new: code | 751 cpu <- new: code |
752 if: (args length) > 2 { | |
753 cpu stepMode | |
754 } | |
669 res <- cpu run | 755 res <- cpu run |
670 print: "Returned value of type: " . (res tag) . "\n" | 756 print: "Ran for " . (cpu cycles) . " cycles\n" |
671 if: (res isError?) { | 757 print: "Returned value of type: " . (getTag: res) . " - value: " . res . "\n" |
672 print: (res msg) . "\n" | |
673 } | |
674 0 | 758 0 |
675 } else: { | 759 } else: { |
676 (file stderr) write: "Failed to open " . (args get: 1) . " for reading\n" | 760 (file stderr) write: "Failed to open " . (args get: 1) . " for reading\n" |
677 1 | 761 1 |
678 } | 762 } |