From 77583a881b03ce38c8065c40641489fe88b61eb2 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Sun, 9 Jan 2022 22:55:59 -0800 Subject: Write the linker. --- encoding-test.csc | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ encoding.csc | 53 +++++++++++++++++++++++++ hash-map-test.csc | 48 +++++++++++++--------- hash-map.csc | 74 +++++++++++++++++++--------------- linker-test.csc | 24 +++++++++++ linker.csc | 67 +++++++++++++++++++++++++++++++ list-test.csc | 20 ++++++++++ list.csc | 23 ++++++++++- match-test.csc | 33 +++++++++------ match.csc | 51 +++++++++--------------- strings-test.csc | 18 ++++++++- strings.csc | 12 ++++-- testing.csc | 12 +++++- 13 files changed, 450 insertions(+), 102 deletions(-) create mode 100644 encoding-test.csc create mode 100644 encoding.csc create mode 100644 linker-test.csc create mode 100644 linker.csc diff --git a/encoding-test.csc b/encoding-test.csc new file mode 100644 index 0000000..a7f4ace --- /dev/null +++ b/encoding-test.csc @@ -0,0 +1,117 @@ +(import (scheme base) + (only (csc testing) test assert-equal) + (csc encoding)) + + +(test encode-const + (assert-equal + '(#xf2 #x3 0 0 0 0 0 0 #xf6 #xff #xff #xff #xff #xff #xff #xff) + (encode '((const -10))))) + + +(test encode-add + (assert-equal + '(#xfc #x3 0 0 0 0 0 0) + (encode '(add)))) + + +(test encode-sub + (assert-equal + '(#x6 #x4 0 0 0 0 0 0) + (encode '(sub)))) + + +(test encode-mul + (assert-equal + '(#x10 #x4 0 0 0 0 0 0) + (encode '(mul)))) + + +(test encode-div + (assert-equal + '(#x1a #x4 0 0 0 0 0 0) + (encode '(div)))) + + +(test encode-mod + (assert-equal + '(#x24 #x4 0 0 0 0 0 0) + (encode '(mod)))) + + +(test encode-alloc + (assert-equal + '(#xda #x7 0 0 0 0 0 0) + (encode '(alloc)))) + + +(test encode-peek + (assert-equal + '(#xe4 #x7 0 0 0 0 0 0 #xa) + (encode '((peek 10))))) + + +(test encode-poke + (assert-equal + '(#xee #x7 0 0 0 0 0 0 #xa) + (encode '((poke 10))))) + + +(test encode-peekbyte + (assert-equal + '(#xf8 #x7 0 0 0 0 0 0) + (encode '(peekbyte)))) + + +(test encode-pokebyte + (assert-equal + '(#x2 #x8 0 0 0 0 0 0) + (encode '(pokebyte)))) + + +(test encode-pop + (assert-equal + '(#xc2 #xb 0 0 0 0 0 0) + (encode '(pop)))) + + +(test encode-local + (assert-equal + '(#xcc #xb 0 0 0 0 0 0 #xa) + (encode '((local 10))))) + + +(test encode-if + (assert-equal + '(#xaa #xf 0 0 0 0 0 0 #xf6 #xff #xff #xff #xff #xff #xff #xff) + (encode '((if -10))))) + + +(test encode-call + (assert-equal + '(#xb4 #xf 0 0 0 0 0 0 #xa) + (encode '((call 10))))) + + +(test encode-ret + (assert-equal + '(#xbe #xf 0 0 0 0 0 0) + (encode '(ret)))) + + +(test encode-exit + (assert-equal + '(#xc8 #xf 0 0 0 0 0 0) + (encode '(exit)))) + + +(test encode-putc + (assert-equal + '(#x92 #x13 0 0 0 0 0 0) + (encode '(putc)))) + + +(test encode-getc + (assert-equal + '(#x9c #x13 0 0 0 0 0 0) + (encode '(getc)))) diff --git a/encoding.csc b/encoding.csc new file mode 100644 index 0000000..21ee88f --- /dev/null +++ b/encoding.csc @@ -0,0 +1,53 @@ +(define-library (csc encoding) + (export encode) + (import (scheme base) + (only (csc match) match)) + (begin + + + (define (right-shift n1 n2) + (floor-quotient n1 (expt 2 n2))) ; Yikes. + + + (define (low-byte n) + (modulo n #x100)) + + + (define (64->le-bytes n) + (list + (low-byte n) + (low-byte (right-shift n 8)) + (low-byte (right-shift n 16)) + (low-byte (right-shift n 24)) + (low-byte (right-shift n 32)) + (low-byte (right-shift n 40)) + (low-byte (right-shift n 48)) + (low-byte (right-shift n 56)))) + + + (define (opcode-switch opcode) + (match opcode + (((! 'const) n) (append (64->le-bytes 1010) (64->le-bytes n))) + ((! 'add) (64->le-bytes 1020)) + ((! 'sub) (64->le-bytes 1030)) + ((! 'mul) (64->le-bytes 1040)) + ((! 'div) (64->le-bytes 1050)) + ((! 'mod) (64->le-bytes 1060)) + ((! 'alloc) (64->le-bytes 2010)) + (((! 'peek) n) (append (64->le-bytes 2020) (list n))) + (((! 'poke) n) (append (64->le-bytes 2030) (list n))) + ((! 'peekbyte) (64->le-bytes 2040)) + ((! 'pokebyte) (64->le-bytes 2050)) + ((! 'pop) (64->le-bytes 3010)) + (((! 'local) n) (append (64->le-bytes 3020) (list n))) + (((! 'if) n) (append (64->le-bytes 4010) (64->le-bytes n))) + (((! 'call) n) (append (64->le-bytes 4020) (list n))) + ((! 'ret) (64->le-bytes 4030)) + ((! 'exit) (64->le-bytes 4040)) + ((! 'putc) (64->le-bytes 5010)) + ((! 'getc) (64->le-bytes 5020)) + (_ (error "invalid opcode" opcode)))) + + + (define (encode program) + (apply append (map opcode-switch program))))) diff --git a/hash-map-test.csc b/hash-map-test.csc index b1b98bd..353e6b4 100644 --- a/hash-map-test.csc +++ b/hash-map-test.csc @@ -2,6 +2,7 @@ (only (csc sort) sort) (only (csc testing) assert-equal + assert-raises test) (csc hash-map)) @@ -14,53 +15,64 @@ (stringstring s1) (symbol->string s2))) -(define (alist->hash-map->alist l) - (hash-map->alist (alist->hash-map hash-symbol symbolmap->alist l) + (map->alist (alist->map hash-symbol symbolalist-singleton - (assert-equal (sort-alist '((a . 1))) (sort-alist (alist->hash-map->alist '((a . 1)))))) +(test map->alist-singleton + (assert-equal (sort-alist '((a . 1))) (sort-alist (alist->map->alist '((a . 1)))))) -(test hash-map->alist-two - (assert-equal (sort-alist '((a . 1) (b . 2))) (sort-alist (alist->hash-map->alist '((a . 1) (b . 2)))))) +(test map->alist-two + (assert-equal (sort-alist '((a . 1) (b . 2))) (sort-alist (alist->map->alist '((a . 1) (b . 2)))))) -(test hash-map->alist-longer +(test map->alist-longer (assert-equal (sort-alist '((a . 1) (b . 2) (c . 3) (d . 4) (e . 5) (f . 6))) - (sort-alist (alist->hash-map->alist '((a . 1) (b . 2) (c . 3) (d . 4) (e . 5) (f . 6)))))) + (sort-alist (alist->map->alist '((a . 1) (b . 2) (c . 3) (d . 4) (e . 5) (f . 6)))))) -(test hash-map->alist-larger +(test map->alist-larger (assert-equal (sort-alist '((f . 5) (m . 1) (n . 7) (q . 3) (x . 8))) - (sort-alist (alist->hash-map->alist '((m . 1) (n . 2) (q . 3) (f . 5) (n . 7) (x . 8)))))) + (sort-alist (alist->map->alist '((m . 1) (n . 2) (q . 3) (f . 5) (n . 7) (x . 8)))))) -(test hash-map->alist-in-order +(test map->alist-in-order (assert-equal (sort-alist '((a . ()) (b . ()) (c . ()) (d . ()) (e . ()) (f . ()) (g . ()) (h . ()))) - (sort-alist (alist->hash-map->alist '((a . ()) (b . ()) (c . ()) (d . ()) (e . ()) (f . ()) (g . ()) (h . ())))))) + (sort-alist (alist->map->alist '((a . ()) (b . ()) (c . ()) (d . ()) (e . ()) (f . ()) (g . ()) (h . ())))))) -(test hash-map->alist-reversed +(test map->alist-reversed (assert-equal (sort-alist '((h . ()) (g . ()) (f . ()) (e . ()) (d . ()) (c . ()) (b . ()) (a . ()))) - (sort-alist (alist->hash-map->alist '((a . ()) (b . ()) (c . ()) (d . ()) (e . ()) (f . ()) (g . ()) (h . ())))))) + (sort-alist (alist->map->alist '((a . ()) (b . ()) (c . ()) (d . ()) (e . ()) (f . ()) (g . ()) (h . ())))))) -(test hash-map->alist-overwrite +(test map->alist-overwrite (assert-equal (sort-alist '((a . 2))) - (sort-alist (alist->hash-map->alist '((a . 1) (a . 2)))))) + (sort-alist (alist->map->alist '((a . 1) (a . 2)))))) -(test hash-map->alist-alternating +(test map->alist-alternating (assert-equal (sort-alist '((h . ()) (g . ()) (i . ()) (f . ()) (j . ()) (e . ()) (k . ()) (d . ()) (l . ()) (c . ()))) - (sort-alist (alist->hash-map->alist '((c . ()) (d . ()) (e . ()) (f . ()) (g . ()) (h . ()) (i . ()) (j . ()) (k . ()) (l . ())))))) + (sort-alist (alist->map->alist '((c . ()) (d . ()) (e . ()) (f . ()) (g . ()) (h . ()) (i . ()) (j . ()) (k . ()) (l . ())))))) + + +(test lookup + (assert-equal + 2 + (lookup (alist->map hash-symbol symbolmap hash-symbol symbolhash-map + alist->map hash-bytevector - hash-map->alist - hash-map-foreach - hash-map-insert - hash-map-lookup - hash-map? - make-hash-map) + map->alist + for-each + insert + lookup + map? + key-not-found-error? + make-map) (import (scheme base) (only (csc format) sprintf)) (begin (define-record-type - (make-key-hash hash k) + (make-key-hash k hash) key-hash? - (hash key-hash-hash) - (k key-hash-value)) + (k key-hash-value) + (hash key-hash-hash)) (define (key-hash (construct-hash-map hash keyalist m) + (define (map->alist m) (let ((alist '())) - (hash-map-foreach + (for-each (lambda (k v) (set! alist (cons (cons k v) alist))) m) alist)) - (define (alist->hash-map hash keymap hash keyutf8 s))) + + + (define (make-label-map program) + (let loop ((m (make-map hash-string string= i end) (raise (make-not-found-error))) ((prefix? match str i) i) - (else (loop (+ 1 i)))))))))) + (else (loop (+ 1 i)))))))) + + + (define (join sep . strings) + (apply string-append (intercalate sep strings))))) diff --git a/testing.csc b/testing.csc index aebc574..a0180e6 100644 --- a/testing.csc +++ b/testing.csc @@ -2,6 +2,7 @@ (export assert assert-equal + assert-raises test test-main) (import (scheme base) @@ -53,7 +54,7 @@ (syntax-rules () ((assert expr) (unless expr - (fatalf "Assertion {} failed." 'expr))))) + (fatalf "(assert {}) failed." 'expr))))) (define-syntax assert-equal @@ -65,6 +66,15 @@ (fatalf "Fatal: {} is not equal to {}.\nleft is {}\nright is {}" 'left 'right x y)))))) + (define-syntax assert-raises + (syntax-rules () + ((assert-raises predicate body body* ...) + (assert + (guard (e ((predicate e) #t)) + body body* ... + #f))))) + + (define (test-main) (if *all-tests-succeeded* (printf "PASS\n") -- cgit v1.3.1