|
16 | 16 | ;; along with toy-bytecode. If not, see <http://www.gnu.org/licenses/>.
|
17 | 17 |
|
18 | 18 | ; utility functions
|
19 |
| -(define last (lambda (l) (if (null? l) l |
20 |
| - (if (not (pair? l)) l |
21 |
| - (if (not (pair? (cdr l))) l |
22 |
| - (if (null? (cdr l)) l |
23 |
| - (last (cdr l)))))))) |
| 19 | +(define last (lambda (l) (if (and (not (null? l)) |
| 20 | + (and (pair? l) |
| 21 | + (and (pair? (cdr l)) |
| 22 | + (not (null? (cdr l)))))) |
| 23 | + (last (cdr l)) |
| 24 | + l))) |
24 | 25 |
|
25 | 26 | (define string-is-numeric? (lambda (str)
|
26 | 27 | (let ((first-char (string-ref str 0))
|
27 | 28 | (strlen (string-length str))
|
28 |
| - (test (lambda (c v) (if (not v) v (char-is-digit? c))))) |
29 |
| - (if (= 0 strlen) #f |
30 |
| - (if (< 1 strlen) |
31 |
| - (if (if (char=? first-char #\-) #t |
32 |
| - (if (char=? first-char #\+) #t |
33 |
| - (char-is-digit? first-char))) |
34 |
| - (string-fold test #t str 1 (string-length str)) |
35 |
| - #f) |
36 |
| - (char-is-digit? first-char)))))) |
| 29 | + (test (lambda (c v) (if v (char-is-digit? c) v)))) |
| 30 | + (and (< 0 strlen) |
| 31 | + (or (and (< 1 strlen) |
| 32 | + (and |
| 33 | + (or (char=? first-char #\-) |
| 34 | + (or (char=? first-char #\+) |
| 35 | + (char-is-digit? first-char))) |
| 36 | + (string-fold test #t str 1 (string-length str)))) |
| 37 | + (char-is-digit? first-char)))))) |
37 | 38 |
|
38 | 39 |
|
39 | 40 | ; The underlying VM uses a tagged memory model that differentiates between
|
|
139 | 140 | (cons "define" compile-define)
|
140 | 141 | (cons "begin" compile-begin)
|
141 | 142 | (cons "quote" compile-quote)
|
| 143 | + (cons "and" compile-and) |
| 144 | + (cons "or" compile-or) |
142 | 145 | )
|
143 | 146 | ))
|
144 | 147 |
|
|
148 | 151 | (lambda (f)
|
149 | 152 | (letrec ((helper (lambda (ss)
|
150 | 153 | (if (null? ss) #f
|
151 |
| - (if (not (string? f)) #f |
152 |
| - (if (string=? f (car (car ss))) (cdr (car ss)) |
153 |
| - (helper (cdr ss)))))))) |
| 154 | + (if (string=? f (car (car ss))) |
| 155 | + (cdr (car ss)) |
| 156 | + (helper (cdr ss))))))) |
154 | 157 | (helper (special-forms)))))
|
155 | 158 |
|
156 | 159 | ; The top-level-env is a list containing the list of symbols
|
|
188 | 191 | ; u-call-* below.
|
189 | 192 |
|
190 | 193 | (define top-level-env
|
191 |
| - (quote ((("=" "equal") |
| 194 | + (quote ((("equal?" "equal") |
| 195 | + ("=" "equal") |
192 | 196 | ("<" "less_than")
|
193 | 197 | ("null?" "null_q")
|
194 | 198 | ("cons" "cons")
|
|
690 | 694 | (u-call-cons)
|
691 | 695 | (lambda ()
|
692 | 696 | (append-instruction (asm-label-definition label))
|
693 |
| - (let ((param-list (car (cdr l))) |
694 |
| - (body (cdr (cdr l)))) |
695 |
| - (let ((r (compile-sequence body |
696 |
| - (cons |
697 |
| - (process-params param-list) |
698 |
| - env) #f))) |
699 |
| - (assembly-funret) |
700 |
| - r)))))) |
| 697 | + (let ((r (compile-sequence (cddr l) |
| 698 | + (cons |
| 699 | + (cadr l) |
| 700 | + env) #f))) |
| 701 | + (assembly-funret) |
| 702 | + r))))) |
701 | 703 |
|
702 | 704 | (define compile-let-bindings
|
703 | 705 | (lambda (bs env)
|
|
796 | 798 | (append-instruction ins-pop)
|
797 | 799 | r)))
|
798 | 800 |
|
| 801 | +(define compile-and |
| 802 | + (lambda (l env rest) |
| 803 | + (let ((out-label (fresh-label))) |
| 804 | + (let ((r1 (compile-sexp (cadr l) env #t)) |
| 805 | + (xx (append-instructions ins-dup |
| 806 | + ins-push false-value |
| 807 | + ins-eq |
| 808 | + ins-push (asm-label-reference out-label) |
| 809 | + ins-jtrue |
| 810 | + ins-pop)) |
| 811 | + (r2 (compile-sexp (caddr l) env #t))) |
| 812 | + (append-instruction (asm-label-definition out-label)) |
| 813 | + (lambda () |
| 814 | + (do-compile-task r1) |
| 815 | + (do-compile-task r2)))))) |
| 816 | + |
| 817 | +(define compile-or |
| 818 | + (lambda (l env rest) |
| 819 | + (let ((out-label (fresh-label)) |
| 820 | + (t2-label (fresh-label))) |
| 821 | + (let ((r1 (compile-sexp (cadr l) env #t)) |
| 822 | + (xx (append-instructions ins-dup |
| 823 | + ins-push false-value |
| 824 | + ins-eq |
| 825 | + ins-push (asm-label-reference t2-label) |
| 826 | + ins-jtrue |
| 827 | + ins-push (asm-label-reference out-label) |
| 828 | + ins-jmp |
| 829 | + (asm-label-definition t2-label) |
| 830 | + ins-pop)) |
| 831 | + (r2 (compile-sexp (caddr l) env #t))) |
| 832 | + (append-instructions (asm-label-definition out-label)) |
| 833 | + (lambda () |
| 834 | + (do-compile-task r1) |
| 835 | + (do-compile-task r2)))))) |
| 836 | + |
799 | 837 | ; when we can detect application of a builtin
|
800 | 838 | ; we can avoid function call overhead and just inline the assembly
|
801 | 839 | (define compile-if
|
|
1492 | 1530 | (lambda () (parse-token (next-token))))
|
1493 | 1531 |
|
1494 | 1532 | ; then run the compiler.
|
1495 |
| -; (display (read-datum (next-non-ws-skip-comments))) |
1496 |
| -; (newline) |
1497 |
| - |
1498 | 1533 | (append-instructions
|
1499 | 1534 | ins-push (asm-label-reference initial-env-label) ins-wtrr)
|
1500 | 1535 | (compiler-run)
|
|
0 commit comments