comparison code/gcc.tp @ 43:6d2cbad5fca9

WIP version of a compiler for the LamCo GCC
author Michael Pavone <pavone@retrodev.com>
date Sun, 27 Jul 2014 01:50:49 -0700
parents
children ec87d53603dd
comparison
equal deleted inserted replaced
42:f1453e8970ca 43:6d2cbad5fca9
1 #{
2 new <- :code {
3 consUsage <- 0
4 dataStack <- []
5 controlStack <- 0
6 stackSize <- 0
7 pc <- 0
8
9 error <- :_msg {
10 #{
11 msg <- { _msg }
12 isInteger? <- { false }
13 isError? <- { true }
14 isClosure? <- { false }
15 isEnvironment? <- { false }
16 isCons? <- { false }
17 isJoin? <- { false }
18 isStop? <- { false }
19 tag <- { "ERROR" }
20 }
21 }
22 _dummy <- #{
23 isInteger? <- { false }
24 isError? <- { false }
25 isClosure? <- { false }
26 isEnvironment? <- { false }
27 isCons? <- { false }
28 isJoin? <- { false }
29 isStop? <- { false }
30 tag <- { "DUMMY" }
31 }
32
33 getTag <- :val {
34 if: (val isInteger?) {
35 "INTEGER"
36 } else: {
37 val tag
38 }
39 }
40
41 push <- :val {
42 dataStack <- val | dataStack
43 stackSize <- stackSize + 1
44 }
45
46 pop <- {
47 if: (dataStack empty?) {
48 error: "datastack empty"
49 } else: {
50 ret <- dataStack value
51 dataStack <- dataStack tail
52 stackSize <- stackSize - 1
53 ret
54 }
55 }
56
57 _curEnv <- #{
58 ld <- :envNum slotNum {
59 error: "invalid environment"
60 }
61 st <- :envNum slotNum val {
62 error: "invalid environment"
63 }
64 rapLoad <- {
65 error: "invalid environment"
66 }
67 isError? <- { false }
68 isEnvironment? <- { true }
69 isJoin? <- { false }
70 isReturn? <- { false }
71 isStop? <- { false }
72 tag <- { "TOPENV" }
73 }
74
75 cons <- :_car _cdr {
76 consUsage <- consUsage + 1
77 #{
78 car <- { _car }
79 cdr <- { _cdr }
80 isInteger? <- { false }
81 isError? <- { false }
82 isClosure? <- { false }
83 isEnvironment? <- { false }
84 isCons? <- { true }
85 isJoin? <- { false }
86 tag <- { "CONS" }
87 }
88 }
89
90
91 env:dummy? <- :_size _parent :_dummy? {
92 consUsage <- consUsage + 1 + _size / 2
93 _arr <- #[]
94 _hasError <- false
95 _error <- false
96 if: _size > 0 {
97 _arr resize: _size
98 i <- 0
99 while: { i < _size } do: {
100 _arr append: 0
101 i <- i + 1
102 }
103
104 if: (not: _dummy?) {
105 i <- _size - 1
106 while: { (not: _hasError) && i >= 0 } do: {
107 val <- pop:
108 if: ((not: (val isInteger?)) && (val isError?)) {
109 _error <- error: "data stack empty while populating env at slot " . i . " of " . _size
110 _hasError <- true
111 } else: {
112 _arr set: i val
113 i <- i - 1
114 }
115 }
116 }
117 }
118 if: _hasError {
119 _error
120 } else: {
121 #{
122 != <- :other {
123 //TODO: implement me properly
124 tag != (other tag)
125 }
126 ld <- :envNum slotNum {
127 if: envNum > 0 {
128 _parent ld: envNum - 1 slotNum
129 } else: {
130 if: _dummy? {
131 error: "attempt to ld from dummy env"
132 } else: {
133 if: slotNum < _size {
134 _arr get: slotNum
135 } else: {
136 error: "attempt to access invalid slot " . slotNum . " in env of size " . _size
137 }
138 }
139 }
140 }
141 st <- :envNum slotNum val {
142 if: envNum > 0 {
143 _parent st: envNum - 1 slotNum val
144 } else: {
145 if: _dummy? {
146 error: "attempt to st to dummy env"
147 } else: {
148 if: slotNum < _size {
149 _arr set: slotNum val
150 _dummy
151 } else: {
152 error: "attempt to access invalid slot " . slotNum . " in env of size " . _size
153 }
154 }
155 }
156 }
157 rapLoad <- :rapSize {
158 if: _dummy? {
159 if: rapSize != _size {
160 _hasError <- true
161 _error <- error: "frame size mismatch for RAP instruction"
162 } else: {
163 i <- 0
164 i <- _size - 1
165 while: { (not: _hasError) && i >= 0 } do: {
166 val <- pop:
167 if: ((not: (val isInteger?)) && (val isError?)) {
168 _error <- error: "data stack empty while populating env at slot " . i . " of " . _size
169 _hasError <- true
170 } else: {
171 _arr set: i val
172 i <- i - 1
173 }
174 }
175 _dummy? <- false
176 }
177 } else: {
178 _hasError <- true
179 _error <- error: "attempt to RAP into non-dummy environment"
180 }
181 if: _hasError { _error } else: { _dummy }
182 }
183 isError? <- { false }
184 isEnvironment? <- { true }
185 isJoin? <- { false }
186 isReturn? <- { false }
187 isStop? <- { false }
188 tag <- { "ENVIRONMENT" }
189 }
190 }
191 }
192
193
194 closure <- :_address {
195 _env <- _curEnv
196 #{
197 address <- { _address }
198 env <- { _env }
199 isInteger? <- { false }
200 isError? <- { false }
201 isClosure? <- { true }
202 isEnvironment? <- { false }
203 isCons? <- { false }
204 isJoin? <- { false }
205 tag <- { "CLOSURE" }
206 }
207 }
208
209 join <- :_address {
210 #{
211 address <- { _address }
212 isError? <- { false }
213 isEnvironment? <- { false }
214 isJoin? <- { true }
215 isReturn? <- { false }
216 isStop? <- { false }
217 tag <- { "JOIN" }
218 }
219 }
220 return <- :_address {
221 #{
222 address <- { _address }
223 isError? <- { false }
224 isEnvironment? <- { false }
225 isJoin? <- { false }
226 isReturn? <- { true }
227 isStop? <- { false }
228 tag <- { "RETURN" }
229 }
230 }
231 stop <- #{
232 isError? <- { false }
233 isEnvironment? <- { false }
234 isJoin? <- { false }
235 isReturn? <- { false }
236 isStop? <- { true }
237 tag <- { "STOP" }
238 }
239
240 _instConstructors <- dict hash
241 _instConstructors set: "LDC" :args {
242 _const <- args get: 0
243 {
244 push: _const
245 _dummy
246 }
247 }
248 _instConstructors set: "LD" :args {
249 _env <- args get: 0
250 _slot <- args get: 1
251 {
252 val <- _curEnv ld: _env _slot
253 if: (not: (val isInteger?)) && (val isError?) {
254 val
255 } else: {
256 push: val
257 _dummy
258 }
259 }
260 }
261 _instConstructors set: "ST" :args {
262 _env <- args get: 0
263 _slot <- args get: 1
264 {
265 val <- pop:
266 if: (not: (val isInteger?)) && (val isError?) {
267 val
268 } else: {
269 _curEnv st: _env _slot val
270 }
271 }
272 }
273
274 binaryConstruct <- macro: :name op a b{
275 quote: (_instConstructors set: name :args {
276 {
277 a <- pop:
278 if: (a isInteger?) {
279 b <- pop:
280 if: (b isInteger?) {
281 push: op
282 _dummy
283 } else: {
284 if: (b isError?) {
285 b
286 } else: {
287 error: "Got wrong type for left param of " . name . " instruction"
288 }
289 }
290 } else: {
291 if: (a isError?) {
292 a
293 } else: {
294 error: "Got wrong type for right param of " . name . " instruction"
295 }
296 }
297 }
298 })
299 }
300
301 binaryConstruct: "ADD" b + a a b
302 binaryConstruct: "SUB" b - a a b
303 binaryConstruct: "MUL" b * a a b
304 binaryConstruct: "DIV" b / a a b
305 binaryConstruct: "CEQ" (if: b = a { 1 } else: { 0 }) a b
306 binaryConstruct: "CGT" (if: b > a { 1 } else: { 0 }) a b
307 binaryConstruct: "CGTE" (if: b >= a { 1 } else: { 0 }) a b
308 _instConstructors set: "ATOM" :args {
309 {
310 val <- pop:
311 if: (val isInteger?) {
312 push: 1
313 _dummy
314 } else: {
315 if: (val isError?) {
316 val
317 } else: {
318 push: 0
319 _dummy
320 }
321 }
322 }
323 }
324 _instConstructors set: "CONS" :args {
325 {
326 a <- pop:
327 if: ((not: (a isInteger?)) && (a isError?)) {
328 a
329 } else: {
330 b <- pop:
331 if: ((not: (b isInteger?)) && (b isError?)) {
332 b
333 } else: {
334 push: (cons: b a)
335 _dummy
336 }
337 }
338 }
339 }
340 _instConstructors set: "CAR" :args {
341 {
342 val <- pop:
343 if: (val isInteger?) {
344 error: "CAR expects CONS cell, got INTEGER instead"
345 } else: {
346 if: (val isError?) {
347 val
348 } else: {
349 if: (val isCons?) {
350 push: (val car)
351 _dummy
352 } else: {
353 error: "CAR expects CONS cell, got " . (val tag) . " instead"
354 }
355 }
356 }
357 }
358 }
359 _instConstructors set: "CDR" :args {
360 {
361 val <- pop:
362 if: (val isInteger?) {
363 error: "CDR expects CONS cell, got integer instead"
364 } else: {
365 if: (val isError?) {
366 val
367 } else: {
368 if: (val isCons?) {
369 push: (val cdr)
370 _dummy
371 } else: {
372 error: "CDR expects CONS cell, got " . (val tag) . " instead"
373 }
374 }
375 }
376 }
377 }
378 _instConstructors set: "SEL" :args {
379 _t <- args get: 0
380 _f <- args get: 1
381 {
382 val <- pop:
383 if: (val isInteger?) {
384 controlStack <- cons: (join: pc) controlStack
385 pc <- if: (val != 0) { _t } else: { _f }
386 _dummy
387 } else: {
388 if: (val isError?) {
389 val
390 } else: {
391 error: "SEL expects INTEGER, got " . (val tag) . " instead"
392 }
393 }
394 }
395 }
396 _instConstructors set: "TSEL" :args {
397 _t <- args get: 0
398 _f <- args get: 1
399 {
400 val <- pop:
401 if: (val isInteger?) {
402 pc <- if: (val != 0) { _t } else: { _f }
403 _dummy
404 } else: {
405 if: (val isError?) {
406 val
407 } else: {
408 error: "TSEL expects INTEGER, got " . (val tag) . " instead"
409 }
410 }
411 }
412 }
413 _instConstructors set: "JOIN" :args {
414 {
415 if: (controlStack isInteger?) {
416 error: "JOIN tried to pull value from empty control stack"
417 } else: {
418 val <- controlStack car
419 controlStack <- controlStack cdr
420 if: (val isJoin?) {
421 pc <- val address
422 _dummy
423 } else: {
424 error: "JOIN expects JOIN cell, got " . (val tag) . " instead"
425 }
426 }
427 }
428 }
429 _instConstructors set: "LDF" :args {
430 _address <- args get: 0
431 {
432 push: (closure: _address)
433 _dummy
434 }
435 }
436 _instConstructors set: "AP" :args {
437 _envSize <- args get: 0
438 {
439 val <- pop:
440 if: (val isInteger?) {
441 error: "AP expects CLOSURE, got INTEGER instead"
442 } else: {
443 if: (val isError?) {
444 val
445 } else: {
446 if: (val isClosure?) {
447 frame <- env: _envSize (val env) dummy?: false
448 if: (frame isError?) {
449 frame
450 } else: {
451 controlStack <- cons: (return: pc+1) (cons: _curEnv controlStack)
452 _curEnv <- frame
453 pc <- val address
454 _dummy
455 }
456 } else: {
457 error: "AP expects CLOSURE, got " . (val tag) . " instead"
458 }
459 }
460 }
461 }
462 }
463 _instConstructors set: "TAP" :args {
464 _envSize <- args get: 0
465 {
466 val <- pop:
467 if: (val isInteger?) {
468 error: "TAP expects CLOSURE, got INTEGER instead"
469 } else: {
470 if: (val isError?) {
471 val
472 } else: {
473 if: (val isClosure?) {
474 frame <- env: _envSize (val env) dummy?: false
475 if: (frame isError?) {
476 frame
477 } else: {
478 _curEnv <- frame
479 pc <- val address
480 _dummy
481 }
482 } else: {
483 error: "TAP expects CLOSURE, got " . (val tag) . " instead"
484 }
485 }
486 }
487 }
488 }
489 _instConstructors set: "RTN" :args {
490 {
491 if: (controlStack isInteger?) {
492 error: "control stack is empty for RTN instruction"
493 } else: {
494 val <- controlStack car
495 controlStack <- controlStack cdr
496 if: (val isReturn?) {
497 _curEnv <- controlStack car
498 controlStack <- controlStack cdr
499 pc <- val address
500 _dummy
501 } else: {
502 if: (val isStop?) {
503 val
504 } else: {
505 error: "RTN expects RETURN, got " . (val tag) . " instead"
506 }
507 }
508 }
509 }
510 }
511 _instConstructors set: "DUM" :args {
512 _envSize <- args get: 0
513 {
514 frame <- env: _envSize _curEnv dummy?: true
515 if: (frame isError?) {
516 frame
517 } else: {
518 _curEnv <- frame
519 _dummy
520 }
521 }
522 }
523 _instConstructors set: "RAP" :args {
524 _envSize <- args get: 0
525 {
526 val <- pop:
527 if: (val isInteger?) {
528 error: "RAP expects CLOSURE, got INTEGER instead"
529 } else: {
530 if: (val isError?) {
531 val
532 } else: {
533 if: (val isClosure?) {
534 res <- _curEnv rapLoad: _envSize
535 if: (not: (res isError?)) {
536 if: (val env) != _curEnv {
537 res <- error: "CLOSURE environment must equal current environment for RAP"
538 } else: {
539 controlStack <- cons: (return: pc+1) (cons: (_curEnv parent) controlStack)
540 pc <- val address
541 }
542 }
543 res
544 } else: {
545 error: "RAP expects CLOSURE, got " . (val tag) . " instead"
546 }
547 }
548 }
549 }
550 }
551 _instConstructors set: "TRAP" :args {
552 _envSize <- args get: 0
553 {
554 val <- pop:
555 if: (val isInteger?) {
556 error: "RAP expects CLOSURE, got INTEGER instead"
557 } else: {
558 if: (val isError?) {
559 val
560 } else: {
561 if: (val isClosure?) {
562 res <- _curEnv rapLoad: _envSize
563 if: (not: (res isError?)) {
564 if: (val env) != _curEnv {
565 res <- error: "CLOSURE environment must equal current environment for RAP"
566 } else: {
567 pc <- val address
568 }
569 }
570 res
571 } else: {
572 error: "RAP expects CLOSURE, got " . (val tag) . " instead"
573 }
574 }
575 }
576 }
577 }
578 _instConstructors set: "STOP" :args {
579 {
580 stop
581 }
582 }
583 _instConstructors set: "DBUG" :args {
584 {
585 val <- pop:
586 if: (not: (val isInteger?)) && (val isError?) {
587 val
588 } else: {
589 print: (string: val) . "\n"
590 _dummy
591 }
592 }
593 }
594 _instConstructors set: "BRK" :args {
595 {
596 _dummy
597 }
598 }
599
600 code <- code map: :i {
601 foobar <- _instConstructors get: (i inst) else: { { stop } }
602 foobar: (i args)
603 }
604
605 #{
606 limit <- 3072 * 1000
607 run <- {
608 cycles <- 0
609 status <- _dummy
610 while: { (not: (status isError?)) && (not: (status isStop?)) } do: {
611 oldpc <- pc
612 if: (cycles >= limit) {
613 status <- error: "cycle limit of " . limit . " exceeded"
614 } else: {
615 if: (pc >= (code length)) {
616 status <- error: "PC walked off end of program"
617 } else: {
618 inst <- code get: pc
619 pc <- -1
620 status <- inst:
621 if: pc = -1 {
622 pc <- oldpc + 1
623 }
624 cycles <- cycles + 1
625 }
626 }
627 }
628 print: "Status: " . (status tag) . "\n"
629 if: (status isStop?) {
630 if: (dataStack empty?) {
631 _dummy
632 } else: {
633 pop:
634 }
635 } else: {
636 status
637 }
638 }
639 }
640 }
641
642 parseLines <- :lines {
643 //remove comments and filter blank lines
644 lines <- (lines map: :line {
645 ((line partitionOn: ";") before) trim
646 }) filter: :line { line != "" }
647 //parse the preprocessed lines
648 lines map: :line {
649 ret <- line partitionOn: " "
650 _inst <- ret before
651 _args <- (((ret after) trim) splitOn: " ") map: :arg { int32: arg }
652 #{
653 inst <- { _inst }
654 args <- { _args }
655 }
656 }
657 }
658
659 parseFile <- :f {
660 parseLines: (f lines)
661 }
662
663 main <- :args {
664 if: (args length) > 1 {
665 f <- file open: (args get: 1)
666 if: (f fd) >= 0 {
667 code <- parseFile: f
668 cpu <- new: code
669 res <- cpu run
670 print: "Returned value of type: " . (res tag) . "\n"
671 if: (res isError?) {
672 print: (res msg) . "\n"
673 }
674 0
675 } else: {
676 (file stderr) write: "Failed to open " . (args get: 1) . " for reading\n"
677 1
678 }
679 } else: {
680 (file stderr) write: "USAGE: gcc FILE\n"
681 1
682 }
683 }
684 }