From 049889df284abacec3600f3bf167abcf9704ef3a Mon Sep 17 00:00:00 2001 From: David Van Horn Date: Wed, 27 Sep 2023 13:06:10 -0400 Subject: [PATCH] Con and Dupe files. --- langs/con/ast.rkt | 13 ++++++++++ langs/con/compile-ops.rkt | 13 ++++++++++ langs/con/compile-stdin.rkt | 13 ++++++++++ langs/con/compile.rkt | 39 ++++++++++++++++++++++++++++ langs/con/interp-prim.rkt | 9 +++++++ langs/con/interp-stdin.rkt | 12 +++++++++ langs/con/interp.rkt | 16 ++++++++++++ langs/con/main.rkt | 13 ++++++++++ langs/con/parse.rkt | 17 ++++++++++++ langs/con/run-stdin.rkt | 12 +++++++++ langs/con/run.rkt | 8 ++++++ langs/con/test/compile.rkt | 8 ++++++ langs/con/test/interp.rkt | 7 +++++ langs/con/test/test-runner.rkt | 27 +++++++++++++++++++ langs/dupe/ast.rkt | 16 ++++++++++++ langs/dupe/compile-ops.rkt | 20 ++++++++++++++ langs/dupe/compile-stdin.rkt | 13 ++++++++++ langs/dupe/compile.rkt | 46 +++++++++++++++++++++++++++++++++ langs/dupe/interp-prim.rkt | 9 +++++++ langs/dupe/interp-stdin.rkt | 12 +++++++++ langs/dupe/interp.rkt | 19 ++++++++++++++ langs/dupe/main.rkt | 13 ++++++++++ langs/dupe/parse.rkt | 21 +++++++++++++++ langs/dupe/run-stdin.rkt | 12 +++++++++ langs/dupe/run.rkt | 7 +++++ langs/dupe/test/compile.rkt | 8 ++++++ langs/dupe/test/interp.rkt | 7 +++++ langs/dupe/test/test-runner.rkt | 39 ++++++++++++++++++++++++++++ langs/dupe/types.rkt | 21 +++++++++++++++ langs/installer.rkt | 6 ++--- 30 files changed, 473 insertions(+), 3 deletions(-) create mode 100644 langs/con/ast.rkt create mode 100644 langs/con/compile-ops.rkt create mode 100644 langs/con/compile-stdin.rkt create mode 100644 langs/con/compile.rkt create mode 100644 langs/con/interp-prim.rkt create mode 100644 langs/con/interp-stdin.rkt create mode 100644 langs/con/interp.rkt create mode 100644 langs/con/main.rkt create mode 100644 langs/con/parse.rkt create mode 100644 langs/con/run-stdin.rkt create mode 100644 langs/con/run.rkt create mode 100644 langs/con/test/compile.rkt create mode 100644 langs/con/test/interp.rkt create mode 100644 langs/con/test/test-runner.rkt create mode 100644 langs/dupe/ast.rkt create mode 100644 langs/dupe/compile-ops.rkt create mode 100644 langs/dupe/compile-stdin.rkt create mode 100644 langs/dupe/compile.rkt create mode 100644 langs/dupe/interp-prim.rkt create mode 100644 langs/dupe/interp-stdin.rkt create mode 100644 langs/dupe/interp.rkt create mode 100644 langs/dupe/main.rkt create mode 100644 langs/dupe/parse.rkt create mode 100644 langs/dupe/run-stdin.rkt create mode 100644 langs/dupe/run.rkt create mode 100644 langs/dupe/test/compile.rkt create mode 100644 langs/dupe/test/interp.rkt create mode 100644 langs/dupe/test/test-runner.rkt create mode 100644 langs/dupe/types.rkt diff --git a/langs/con/ast.rkt b/langs/con/ast.rkt new file mode 100644 index 00000000..d68c3e6f --- /dev/null +++ b/langs/con/ast.rkt @@ -0,0 +1,13 @@ +#lang racket +(provide Lit Prim1 IfZero) + +;; type Expr = (Lit Integer) +;; | (Prim1 Op1 Expr) +;; | (IfZero Expr Expr Expr) + +;; type Op1 = 'add1 | 'sub1 + +(struct Lit (i) #:prefab) +(struct Prim1 (p e) #:prefab) +(struct IfZero (e1 e2 e3) #:prefab) + diff --git a/langs/con/compile-ops.rkt b/langs/con/compile-ops.rkt new file mode 100644 index 00000000..8f6bd44c --- /dev/null +++ b/langs/con/compile-ops.rkt @@ -0,0 +1,13 @@ +#lang racket +(provide compile-op1) +(require "ast.rkt") +(require a86/ast) + +(define rax 'rax) + +;; Op1 -> Asm +(define (compile-op1 p) + (match p + ['add1 (Add rax 1)] + ['sub1 (Sub rax 1)])) + diff --git a/langs/con/compile-stdin.rkt b/langs/con/compile-stdin.rkt new file mode 100644 index 00000000..532ee0eb --- /dev/null +++ b/langs/con/compile-stdin.rkt @@ -0,0 +1,13 @@ +#lang racket +(provide main) +(require "parse.rkt") +(require "compile.rkt") +(require a86/printer) + +;; -> Void +;; Compile contents of stdin, +;; emit asm code on stdout +(define (main) + (read-line) ; ignore #lang racket line + (asm-display (compile (parse (read))))) + diff --git a/langs/con/compile.rkt b/langs/con/compile.rkt new file mode 100644 index 00000000..59f077a6 --- /dev/null +++ b/langs/con/compile.rkt @@ -0,0 +1,39 @@ +#lang racket +(provide (all-defined-out)) +(require "ast.rkt") +(require "compile-ops.rkt") +(require a86/ast) + +(define rax 'rax) +;; Expr -> Asm +(define (compile e) + (prog (Global 'entry) + (Label 'entry) + (compile-e e) + (Ret))) + +;; Expr -> Asm +(define (compile-e e) + (match e + [(Lit i) (seq (Mov rax i))] + [(Prim1 p e) (compile-prim1 p e)] + [(IfZero e1 e2 e3) + (compile-ifzero e1 e2 e3)])) + +;; Op1 Expr -> Asm +(define (compile-prim1 p e) + (seq (compile-e e) + (compile-op1 p))) + +;; Expr Expr Expr -> Asm +(define (compile-ifzero e1 e2 e3) + (let ((l1 (gensym 'ifz)) + (l2 (gensym 'ifz))) + (seq (compile-e e1) + (Cmp rax 0) + (Jne l1) + (compile-e e2) + (Jmp l2) + (Label l1) + (compile-e e3) + (Label l2)))) diff --git a/langs/con/interp-prim.rkt b/langs/con/interp-prim.rkt new file mode 100644 index 00000000..2d3b7ffb --- /dev/null +++ b/langs/con/interp-prim.rkt @@ -0,0 +1,9 @@ +#lang racket +(provide interp-prim1) + +;; Op1 Integer -> Integer +(define (interp-prim1 op i) + (match op + ['add1 (add1 i)] + ['sub1 (sub1 i)])) + diff --git a/langs/con/interp-stdin.rkt b/langs/con/interp-stdin.rkt new file mode 100644 index 00000000..ce4885f7 --- /dev/null +++ b/langs/con/interp-stdin.rkt @@ -0,0 +1,12 @@ +#lang racket +(provide main) +(require "parse.rkt") +(require "interp.rkt") + +;; -> Void +;; Parse and interpret contents of stdin, +;; print result on stdout +(define (main) + (read-line) ; ignore #lang racket line + (println (interp (parse (read))))) + diff --git a/langs/con/interp.rkt b/langs/con/interp.rkt new file mode 100644 index 00000000..30fc6e04 --- /dev/null +++ b/langs/con/interp.rkt @@ -0,0 +1,16 @@ +#lang racket +(provide interp) +(require "ast.rkt") +(require "interp-prim.rkt") + +;; Expr -> Integer +(define (interp e) + (match e + [(Lit i) i] + [(Prim1 p e) (interp-prim1 p (interp e))] + [(IfZero e1 e2 e3) + (if (zero? (interp e1)) + (interp e2) + (interp e3))])) + + diff --git a/langs/con/main.rkt b/langs/con/main.rkt new file mode 100644 index 00000000..e0e38924 --- /dev/null +++ b/langs/con/main.rkt @@ -0,0 +1,13 @@ +#lang racket +(require "ast.rkt") +(require "parse.rkt") +(require "interp.rkt") +(require "compile.rkt") +(require "run.rkt") +(provide (all-from-out "ast.rkt")) +(provide (all-from-out "parse.rkt")) +(provide (all-from-out "interp.rkt")) +(provide (all-from-out "compile.rkt")) +(provide (all-from-out "run.rkt")) + + diff --git a/langs/con/parse.rkt b/langs/con/parse.rkt new file mode 100644 index 00000000..792f883d --- /dev/null +++ b/langs/con/parse.rkt @@ -0,0 +1,17 @@ +#lang racket +(provide parse) +(require "ast.rkt") + +;; S-Expr -> Expr +(define (parse s) + (match s + [(? exact-integer?) (Lit s)] + [(list (? op1? o) e) (Prim1 o (parse e))] + ;; NEW: + [(list 'if (list 'zero? e1) e2 e3) + (IfZero (parse e1) (parse e2) (parse e3))] + [_ (error "Parse error")])) + +(define (op1? x) + (memq x '(add1 sub1))) + diff --git a/langs/con/run-stdin.rkt b/langs/con/run-stdin.rkt new file mode 100644 index 00000000..16cf99e0 --- /dev/null +++ b/langs/con/run-stdin.rkt @@ -0,0 +1,12 @@ +#lang racket +(provide main) +(require "parse.rkt") +(require "compile.rkt") +(require "run.rkt") + +;; -> Void +;; Compile contents of stdin and use asm-interp to run +(define (main) + (read-line) ; ignore #lang racket line + (run (compile (parse (read))))) + diff --git a/langs/con/run.rkt b/langs/con/run.rkt new file mode 100644 index 00000000..1191f553 --- /dev/null +++ b/langs/con/run.rkt @@ -0,0 +1,8 @@ +#lang racket +(require a86/interp) +(provide run) + +;; Asm -> Integer +(define (run is) + (asm-interp is)) + diff --git a/langs/con/test/compile.rkt b/langs/con/test/compile.rkt new file mode 100644 index 00000000..560e6f59 --- /dev/null +++ b/langs/con/test/compile.rkt @@ -0,0 +1,8 @@ +#lang racket +(require "../compile.rkt") +(require "../parse.rkt") +(require "../run.rkt") +(require "test-runner.rkt") + +(test (λ (e) (run (compile (parse e))))) + diff --git a/langs/con/test/interp.rkt b/langs/con/test/interp.rkt new file mode 100644 index 00000000..41aa8c04 --- /dev/null +++ b/langs/con/test/interp.rkt @@ -0,0 +1,7 @@ +#lang racket +(require "../interp.rkt") +(require "../parse.rkt") +(require "test-runner.rkt") + +(test (λ (e) (interp (parse e)))) + diff --git a/langs/con/test/test-runner.rkt b/langs/con/test/test-runner.rkt new file mode 100644 index 00000000..4428c634 --- /dev/null +++ b/langs/con/test/test-runner.rkt @@ -0,0 +1,27 @@ +#lang racket +(provide test) +(require rackunit) + +(define (test run) + (begin ;; Abscond + (check-equal? (run 7) 7) + (check-equal? (run -8) -8)) + + (begin ;; Blackmail + (check-equal? (run '(add1 (add1 7))) 9) + (check-equal? (run '(add1 (sub1 7))) 7)) + + (begin ;; Con + (check-equal? (run '(if (zero? 0) 1 2)) 1) + (check-equal? (run '(if (zero? 1) 1 2)) 2) + (check-equal? (run '(if (zero? -7) 1 2)) 2) + (check-equal? (run '(if (zero? 0) + (if (zero? 1) 1 2) + 7)) + 2) + (check-equal? (run '(if (zero? (if (zero? 0) 1 0)) + (if (zero? 1) 1 2) + 7)) + 7))) + + diff --git a/langs/dupe/ast.rkt b/langs/dupe/ast.rkt new file mode 100644 index 00000000..50183b13 --- /dev/null +++ b/langs/dupe/ast.rkt @@ -0,0 +1,16 @@ +#lang racket +(provide Lit Prim1 If) + +;; type Expr = (Lit Datum) +;; | (Prim1 Op1 Expr) +;; | (If Expr Expr Expr) + +;; type Datum = Integer +;; | Boolean + +;; type Op1 = 'add1 | 'sub1 +;; | 'zero? + +(struct Lit (d) #:prefab) +(struct Prim1 (p e) #:prefab) +(struct If (e1 e2 e3) #:prefab) diff --git a/langs/dupe/compile-ops.rkt b/langs/dupe/compile-ops.rkt new file mode 100644 index 00000000..0ef4ebc8 --- /dev/null +++ b/langs/dupe/compile-ops.rkt @@ -0,0 +1,20 @@ +#lang racket +(provide compile-op1) +(require "ast.rkt") +(require "types.rkt") +(require a86/ast) + +(define rax 'rax) +(define r9 'r9) + +;; Op1 -> Asm +(define (compile-op1 p) + (match p + ['add1 (Add rax (value->bits 1))] + ['sub1 (Sub rax (value->bits 1))] + ['zero? + (seq (Cmp rax 0) + (Mov rax (value->bits #f)) + (Mov r9 (value->bits #t)) + (Cmove rax r9))])) + diff --git a/langs/dupe/compile-stdin.rkt b/langs/dupe/compile-stdin.rkt new file mode 100644 index 00000000..532ee0eb --- /dev/null +++ b/langs/dupe/compile-stdin.rkt @@ -0,0 +1,13 @@ +#lang racket +(provide main) +(require "parse.rkt") +(require "compile.rkt") +(require a86/printer) + +;; -> Void +;; Compile contents of stdin, +;; emit asm code on stdout +(define (main) + (read-line) ; ignore #lang racket line + (asm-display (compile (parse (read))))) + diff --git a/langs/dupe/compile.rkt b/langs/dupe/compile.rkt new file mode 100644 index 00000000..fa817ac1 --- /dev/null +++ b/langs/dupe/compile.rkt @@ -0,0 +1,46 @@ +#lang racket +(provide (all-defined-out)) +(require "ast.rkt") +(require "compile-ops.rkt") +(require "types.rkt") +(require a86/ast) + +(define rax 'rax) + +;; Expr -> Asm +(define (compile e) + (prog (Global 'entry) + (Label 'entry) + (compile-e e) + (Ret))) + +;; Expr -> Asm +(define (compile-e e) + (match e + [(Lit d) (compile-value d)] + [(Prim1 p e) (compile-prim1 p e)] + [(If e1 e2 e3) + (compile-if e1 e2 e3)])) + +;; Value -> Asm +(define (compile-value v) + (seq (Mov rax (value->bits v)))) + +;; Op1 Expr -> Asm +(define (compile-prim1 p e) + (seq (compile-e e) + (compile-op1 p))) + +;; Expr Expr Expr -> Asm +(define (compile-if e1 e2 e3) + (let ((l1 (gensym 'if)) + (l2 (gensym 'if))) + (seq (compile-e e1) + (Cmp rax (value->bits #f)) + (Je l1) + (compile-e e2) + (Jmp l2) + (Label l1) + (compile-e e3) + (Label l2)))) + diff --git a/langs/dupe/interp-prim.rkt b/langs/dupe/interp-prim.rkt new file mode 100644 index 00000000..e0ea0720 --- /dev/null +++ b/langs/dupe/interp-prim.rkt @@ -0,0 +1,9 @@ +#lang racket +(provide interp-prim1) + +;; Op1 Value -> Value +(define (interp-prim1 op v) + (match op + ['add1 (add1 v)] + ['sub1 (sub1 v)] + ['zero? (zero? v)])) diff --git a/langs/dupe/interp-stdin.rkt b/langs/dupe/interp-stdin.rkt new file mode 100644 index 00000000..ce4885f7 --- /dev/null +++ b/langs/dupe/interp-stdin.rkt @@ -0,0 +1,12 @@ +#lang racket +(provide main) +(require "parse.rkt") +(require "interp.rkt") + +;; -> Void +;; Parse and interpret contents of stdin, +;; print result on stdout +(define (main) + (read-line) ; ignore #lang racket line + (println (interp (parse (read))))) + diff --git a/langs/dupe/interp.rkt b/langs/dupe/interp.rkt new file mode 100644 index 00000000..920f0920 --- /dev/null +++ b/langs/dupe/interp.rkt @@ -0,0 +1,19 @@ +#lang racket +(provide interp) +(require "ast.rkt") +(require "interp-prim.rkt") + +;; type Value = +;; | Integer +;; | Boolean + +;; Expr -> Value +(define (interp e) + (match e + [(Lit d) d] + [(Prim1 p e) + (interp-prim1 p (interp e))] + [(If e1 e2 e3) + (if (interp e1) + (interp e2) + (interp e3))])) diff --git a/langs/dupe/main.rkt b/langs/dupe/main.rkt new file mode 100644 index 00000000..e0e38924 --- /dev/null +++ b/langs/dupe/main.rkt @@ -0,0 +1,13 @@ +#lang racket +(require "ast.rkt") +(require "parse.rkt") +(require "interp.rkt") +(require "compile.rkt") +(require "run.rkt") +(provide (all-from-out "ast.rkt")) +(provide (all-from-out "parse.rkt")) +(provide (all-from-out "interp.rkt")) +(provide (all-from-out "compile.rkt")) +(provide (all-from-out "run.rkt")) + + diff --git a/langs/dupe/parse.rkt b/langs/dupe/parse.rkt new file mode 100644 index 00000000..673a0266 --- /dev/null +++ b/langs/dupe/parse.rkt @@ -0,0 +1,21 @@ +#lang racket +(provide parse) +(require "ast.rkt") + +;; S-Expr -> Expr +(define (parse s) + (match s + [(? datum?) (Lit s)] + [(list (? op1? o) e) (Prim1 o (parse e))] + [(list 'if e1 e2 e3) + (If (parse e1) (parse e2) (parse e3))] + [_ (error "Parse error")])) + +;; Any -> Boolean +(define (datum? x) + (or (exact-integer? x) + (boolean? x))) + +(define (op1? x) + (memq x '(add1 sub1 zero?))) + diff --git a/langs/dupe/run-stdin.rkt b/langs/dupe/run-stdin.rkt new file mode 100644 index 00000000..16cf99e0 --- /dev/null +++ b/langs/dupe/run-stdin.rkt @@ -0,0 +1,12 @@ +#lang racket +(provide main) +(require "parse.rkt") +(require "compile.rkt") +(require "run.rkt") + +;; -> Void +;; Compile contents of stdin and use asm-interp to run +(define (main) + (read-line) ; ignore #lang racket line + (run (compile (parse (read))))) + diff --git a/langs/dupe/run.rkt b/langs/dupe/run.rkt new file mode 100644 index 00000000..227703c1 --- /dev/null +++ b/langs/dupe/run.rkt @@ -0,0 +1,7 @@ +#lang racket +(require a86/interp) +(require "types.rkt") +(provide run);; Asm -> Value +(define (run is) + (bits->value (asm-interp is))) + diff --git a/langs/dupe/test/compile.rkt b/langs/dupe/test/compile.rkt new file mode 100644 index 00000000..560e6f59 --- /dev/null +++ b/langs/dupe/test/compile.rkt @@ -0,0 +1,8 @@ +#lang racket +(require "../compile.rkt") +(require "../parse.rkt") +(require "../run.rkt") +(require "test-runner.rkt") + +(test (λ (e) (run (compile (parse e))))) + diff --git a/langs/dupe/test/interp.rkt b/langs/dupe/test/interp.rkt new file mode 100644 index 00000000..41aa8c04 --- /dev/null +++ b/langs/dupe/test/interp.rkt @@ -0,0 +1,7 @@ +#lang racket +(require "../interp.rkt") +(require "../parse.rkt") +(require "test-runner.rkt") + +(test (λ (e) (interp (parse e)))) + diff --git a/langs/dupe/test/test-runner.rkt b/langs/dupe/test/test-runner.rkt new file mode 100644 index 00000000..7dcac9f1 --- /dev/null +++ b/langs/dupe/test/test-runner.rkt @@ -0,0 +1,39 @@ +#lang racket +(provide test) +(require rackunit) + +(define (test run) + (begin ;; Abscond + (check-equal? (run 7) 7) + (check-equal? (run -8) -8)) + + (begin ;; Blackmail + (check-equal? (run '(add1 (add1 7))) 9) + (check-equal? (run '(add1 (sub1 7))) 7)) + + (begin ;; Con + (check-equal? (run '(if (zero? 0) 1 2)) 1) + (check-equal? (run '(if (zero? 1) 1 2)) 2) + (check-equal? (run '(if (zero? -7) 1 2)) 2) + (check-equal? (run '(if (zero? 0) + (if (zero? 1) 1 2) + 7)) + 2) + (check-equal? (run '(if (zero? (if (zero? 0) 1 0)) + (if (zero? 1) 1 2) + 7)) + 7)) + + (begin ;; Dupe + (check-equal? (run #t) #t) + (check-equal? (run #f) #f) + (check-equal? (run '(if #t 1 2)) 1) + (check-equal? (run '(if #f 1 2)) 2) + (check-equal? (run '(if 0 1 2)) 1) + (check-equal? (run '(if #t 3 4)) 3) + (check-equal? (run '(if #f 3 4)) 4) + (check-equal? (run '(if 0 3 4)) 3) + (check-equal? (run '(zero? 4)) #f) + (check-equal? (run '(zero? 0)) #t))) + + diff --git a/langs/dupe/types.rkt b/langs/dupe/types.rkt new file mode 100644 index 00000000..0ba82665 --- /dev/null +++ b/langs/dupe/types.rkt @@ -0,0 +1,21 @@ +#lang racket +(provide (all-defined-out)) +(define int-shift 1) +(define mask-int #b1) +(define type-int #b0) + +(define (bits->value b) + (cond [(= b (value->bits #t)) #t] + [(= b (value->bits #f)) #f] + [(int-bits? b) + (arithmetic-shift b (- int-shift))] + [else (error "invalid bits")])) + +(define (value->bits v) + (cond [(eq? v #t) #b01] + [(eq? v #f) #b11] + [(integer? v) (arithmetic-shift v int-shift)])) + +(define (int-bits? v) + (= type-int (bitwise-and v mask-int))) + diff --git a/langs/installer.rkt b/langs/installer.rkt index 0b20b6e4..1669b352 100644 --- a/langs/installer.rkt +++ b/langs/installer.rkt @@ -10,9 +10,9 @@ (main (path->string (collection-file-path "src/" "ziggy")) own (cdr (assoc lang-name '(#;("abscond" . "A") - ("blackmail" . "B") - ("con" . "C") - ("dupe" . "D0") + #;("blackmail" . "B") + #;("con" . "C") + #;("dupe" . "D0") ("dodger" . "D1") ("evildoer" . "E0") ("extort" . "E1")