Skip to content

Commit c54ec93

Browse files
committed
Fall 2020 here we go
1 parent 375a9ae commit c54ec93

11 files changed

+296
-174
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
Assignment 4: Variables, Binding, and Characters
44

5-
See: http://www.cs.umd.edu/class/spring2020/cmsc430/Assignments.html
5+
See: http://www.cs.umd.edu/class/fall2020/cmsc430/Assignments.html

Diff for: ast.rkt

+106-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,115 @@
11
#lang racket
2+
(provide (all-defined-out))
3+
4+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5+
;;;;;; The grammar of our AST
6+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7+
28
;; type Expr =
39
;; | Integer
410
;; | Boolean
511
;; | Character
612
;; | Variable
7-
;; | `(,Prim ,Expr)
8-
;; | `(if ,Expr ,Expr ,Expr)
9-
;; | `(cond ,@Clauses [else ,Expr])
10-
;; | `(let ,Bindings ,Expr)
11-
;; | `(let* ,Bindings ,Expr)
13+
;; | Prim PrimOp Expr
14+
;; | if Expr Expr Expr
15+
;; | cond (Clause list) Expr
16+
;; | let (Binding list) Expr
17+
18+
;; type PrimOp =
19+
;; | add1 | sub1 | zero? | abs | - | char? | integer? | boolean?
20+
;; | integer->char | char->integer
21+
22+
;; type Clause = Expr Expr
23+
;; type Binding = Variable Expr
24+
25+
;; type Variable = Symbol (except 'let, 'add1, etc.)
26+
27+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28+
;;;;;; The AST data structure
29+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30+
31+
;; The AST can be viewed as having 'kinds' of nodes.
32+
;;
33+
;; * The nodes that represnt an expression themselves
34+
;;
35+
;; * The nodes that are part of an expression, but no an expression themselves
36+
37+
;; The below are the former:
38+
39+
(struct int-e (i) #:transparent)
40+
(struct bool-e (b) #:transparent)
41+
(struct char-e (c) #:transparent)
42+
(struct var-e (v) #:transparent)
43+
(struct prim-e (p e) #:transparent)
44+
(struct if-e (e t f) #:transparent)
45+
(struct cond-e (cs el) #:transparent)
46+
(struct let-e (bs b) #:transparent)
47+
48+
;; The next two are the latter:
49+
50+
;; a clause now takes an _arbitrary_ expression and a body.
51+
;; This is different than assignment 3! If you want to understand
52+
;; why, look at the lecture notes for Dupe.
53+
(struct clause (e body) #:transparent)
54+
55+
;; A binding holds a symbol representing the bound variable and
56+
;; Expr that represents the value that will be bound to that variable
57+
(struct binding (v e) #:transparent)
58+
59+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
60+
;;;;;; AST utility functions (getters)
61+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62+
63+
;; It will sometimes be useful to get the list of all the variables that are
64+
;; introduced by a `let`
65+
;; [Binding] -> [Symbol]
66+
(define (get-vars bs)
67+
(match bs
68+
['() '()]
69+
[(cons (binding v _) bs) (cons v (get-vars bs))]))
70+
71+
;; Get all of the _definitions_ from a list of bindings
72+
;; [Binding] -> [Expr]
73+
(define (get-defs bs)
74+
(match bs
75+
['() '()]
76+
[(cons (binding _ def) bs) (cons def (get-defs bs))]))
77+
78+
79+
;; Get all of the predicate expressions from a list of clauses
80+
;; [Binding] -> [Expr]
81+
(define (get-preds cs)
82+
(match cs
83+
['() '()]
84+
[(cons (clause p _) cs) (cons p (get-preds cs))]))
85+
86+
;; Get all of the bodies expressions from a list of clauses
87+
;; [Binding] -> [Expr]
88+
(define (get-bods cs)
89+
(match cs
90+
['() '()]
91+
[(cons (clause _ b) cs) (cons b (get-preds cs))]))
1292

13-
;; type Prim =
14-
;; | 'add1 | 'sub1 | 'zero? | 'abs | '- | 'char? | 'integer? | 'boolean?
15-
;; | 'integer->char | 'char->integer
93+
;; Given an AST, construct an sexpr that has the same shape
94+
(define (ast->sexpr a)
95+
(match a
96+
[(int-e i) `(int-e ,i)]
97+
[(bool-e b) `(bool-e ,b)]
98+
[(char-e c) `(char-e ,c)]
99+
[(var-e v) `(var-e ,v)]
100+
[(prim-e p e) `(prim-e ,p ,e)]
101+
[(if-e e t f) `(if-e ,(ast->sexpr e)
102+
,(ast->sexpr t)
103+
,(ast->sexpr f))]
104+
[(cond-e cs f) `(cond-e ,(clauses->sexpr cs) ,(ast->sexpr f))]
105+
[(let-e bs b) `(let-e ,(binding->sexpr bs) ,(ast->sexpr b))]))
16106

17-
;; type Clauses = (Listof `(,Expr ,Expr))
18-
;; type Bindings = (Listof `(,Variable ,Expr))
107+
(define (binding->sexpr bnds)
108+
(match bnds
109+
['() '()]
110+
[(cons (binding v e) bnds) `((,v ,(ast->sexpr e)) ,@(binding->sexpr bnds))]))
19111

20-
;; type Variable = Symbol (except 'let, 'let*, 'add1, etc.)
112+
(define (clauses->sexpr cs)
113+
(match cs
114+
['() '()]
115+
[(cons (clause e b) cs) `((,(ast->sexpr e) ,(ast->sexpr b)) ,@(clauses->sexpr cs))]))

Diff for: compile.rkt

+50-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
#lang racket
22
(provide (all-defined-out))
3+
(require "ast.rkt")
4+
5+
;; This assignment should be completed individually.
6+
7+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8+
;; I pledge on my honor that I have not given or received any
9+
;; unauthorized assistance on this assignment.
10+
;;
11+
;; Name: TODO
12+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
313

414
;; Expr -> Asm
515
(define (compile e)
@@ -10,35 +20,24 @@
1020
(push rbp) ; push before calling
1121
(call error)))
1222

23+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24+
;;;;;; Compiling expressions and their sub-parts
25+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26+
27+
;; You'll need to add the ability to compile `char-e` nodes
28+
1329
;; Expr CEnv -> Asm
1430
(define (compile-e e c)
1531
(match e
16-
[(? integer? i)
32+
[(int-e i)
1733
`((mov rax ,(* i 4)))]
18-
[(? boolean? b)
34+
[(bool-e b)
1935
`((mov rax ,(if b #b101 #b001)))]
20-
[`(add1 ,e0)
21-
(let ((c0 (compile-e e0 c)))
22-
`(,@c0
23-
,@assert-integer
24-
(add rax 4)))]
25-
[`(sub1 ,e0)
36+
[(prim-e p e0)
2637
(let ((c0 (compile-e e0 c)))
27-
`(,@c0
28-
,@assert-integer
29-
(sub rax 4)))]
30-
[`(zero? ,e0)
31-
(let ((c0 (compile-e e0 c))
32-
(l0 (gensym))
33-
(l1 (gensym)))
34-
`(,@c0
35-
,@assert-integer
36-
(cmp rax 0)
37-
(mov rax #b001) ; #f
38-
(jne ,l0)
39-
(mov rax #b101) ; #t
40-
,l0))]
41-
[`(if ,e0 ,e1 ,e2)
38+
`(,@c0
39+
,@(compile-prim p)))]
40+
[(if-e e0 e1 e2)
4241
(let ((c0 (compile-e e0 c))
4342
(c1 (compile-e e1 c))
4443
(c2 (compile-e e2 c))
@@ -54,23 +53,46 @@
5453
,l1))]
5554

5655
;; TODO: make sure this works with your generalized let
57-
[(? symbol? x)
58-
(let ((i (lookup x c)))
56+
[(var-e v)
57+
(let ((i (lookup v c)))
5958
`((mov rax (offset rsp ,(- (add1 i))))))]
6059

6160
;; TODO: generalize
62-
[`(let ((,x ,e0)) ,e1)
63-
(let ((c0 (compile-e e0 c))
64-
(c1 (compile-e e1 (cons x c))))
61+
[(let-e (list (binding x def)) bod)
62+
(let ((c0 (compile-e def c))
63+
(c1 (compile-e bod (cons x c))))
6564
`(,@c0
6665
(mov (offset rsp ,(- (add1 (length c)))) rax)
6766
,@c1))]
6867

68+
;; TODO
69+
#;...))
6970

71+
(define (compile-prim p)
72+
(match p
73+
['add1 `(,@assert-integer
74+
(add rax 4))]
75+
['sub1 `(,@assert-integer
76+
(sub rax 4))]
77+
['zero?
78+
(let ((l0 (gensym))
79+
(l1 (gensym)))
80+
`(,@assert-integer
81+
(cmp rax 0)
82+
(mov rax #b001) ; #f
83+
(jne ,l0)
84+
(mov rax #b101) ; #t
85+
,l0))]
86+
87+
;; Primitives still left: char?, integer?, boolean?,
88+
;; char->integer, integer->char, neg, abs.
89+
;; You should be able to harvest a significant amount from your submission
90+
;; to assignment#3
7091
;; TODO
7192
#;...))
7293

7394

95+
7496
;; Variable CEnv -> Natural
7597
(define (lookup x cenv)
7698
(match cenv

Diff for: interp.rkt

+28-57
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#lang racket
22
(provide (all-defined-out))
3+
(require (only-in "syntax.rkt" prim?))
4+
5+
(require "ast.rkt")
36

47
;; type Value =
58
;; | Integer
@@ -17,40 +20,28 @@
1720
;; Expr REnv -> Answer
1821
(define (interp-env e r)
1922
(match e
20-
[(? value? v) v]
21-
[(list (? prim? p) e)
23+
[(int-e i) i]
24+
[(bool-e b) b]
25+
[(char-e c) c]
26+
[(prim-e p e)
2227
(let ((a (interp-env e r)))
2328
(interp-prim p a))]
24-
[`(if ,e0 ,e1 ,e2)
25-
(match (interp-env e0 r)
29+
[(if-e i t f)
30+
(match (interp-env i r)
2631
['err 'err]
2732
[v
2833
(if v
29-
(interp-env e1 r)
30-
(interp-env e2 r))])]
31-
[(? symbol? x)
32-
(lookup r x)]
33-
[`(let ,(list `(,xs ,es) ...) ,e)
34-
(match (interp-envs es r)
35-
['err 'err]
36-
[vs
37-
(if (any-err? vs)
38-
'err
39-
(interp-env e (append (zip xs vs) r)))])]
40-
[`(let* ,(list bs ...) ,e)
41-
(match (map-accum-env bs r)
42-
['err 'err]
43-
[new-r
44-
(interp-env e new-r)])]
45-
[(list 'cond cs ... `(else ,en))
46-
(interp-cond-env cs en r)]))
47-
48-
(define (any-err? xs)
49-
(match xs
50-
['() #f]
51-
['err #t]
52-
[(cons y ys)
53-
(if (eq? 'err y) #t (any-err? ys))]))
34+
(interp-env t r)
35+
(interp-env f r))])]
36+
[(var-e v)
37+
(lookup r v)]
38+
[(let-e (list (binding xs es) ...) b)
39+
(match (interp-envs es r)
40+
['err 'err]
41+
[vs
42+
(interp-env b (append (zip xs vs) r))])]
43+
[(cond-e cs f)
44+
(interp-cond-env cs f r)]))
5445

5546
;; (Listof Expr) REnv -> (Listof Value) | 'err
5647
(define (interp-envs es r)
@@ -61,42 +52,22 @@
6152
['err 'err]
6253
[v (cons v (interp-envs es r))])]))
6354

64-
;; (Listof (Symbol Expr)) REnv -> REnv | 'err
65-
(define (map-accum-env bs r)
66-
(match bs
67-
['() r]
68-
[(cons (list b e) bss)
69-
(match (interp-env e r)
70-
['err 'err]
71-
[v (map-accum-env bss (cons (list b v) r))])]))
72-
73-
;; (Listof (List Expr Expr)) Expr REnv -> Answer
74-
(define (interp-cond-env cs en r)
55+
;; (Listof (clause i b)) Expr REnv -> Answer
56+
(define (interp-cond-env cs f r)
7557
(match cs
76-
['() (interp-env en r)]
77-
[(cons `(,eq ,ea) cs)
78-
(match (interp-env eq r)
58+
['() (interp-env f r)]
59+
[(cons (clause i b) css)
60+
(match (interp-env i r)
7961
['err 'err]
8062
[v
8163
(if v
82-
(interp-env ea r)
83-
(interp-cond-env cs en r))])]))
84-
85-
;; Any -> Boolean
86-
(define (prim? x)
87-
(and (symbol? x)
88-
(memq x '(add1 sub1 zero? abs - char? boolean? integer? integer->char char->integer))))
89-
90-
;; Any -> Boolean
91-
(define (value? x)
92-
(or (integer? x)
93-
(boolean? x)
94-
(char? x)))
64+
(interp-env b r)
65+
(interp-cond-env css f r))])]))
9566

9667
;; Prim Answer -> Answer
9768
(define (interp-prim p a)
9869
(match (list p a)
99-
[(list p 'err) 'err]
70+
[(list _ 'err) 'err]
10071
[(list '- (? integer? i0)) (- i0)]
10172
[(list 'abs (? integer? i0)) (abs i0)]
10273
[(list 'add1 (? integer? i0)) (+ i0 1)]

Diff for: lex.rkt

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
(define prims
5353
'("add1" "sub1" "zero?" "abs" "-" "integer->char" "char->integer" "char?" "integer?" "boolean?"))
5454

55-
(define kws '("cond" "if" "let" "let*" "else"))
55+
(define kws '("cond" "if" "let" "else"))
5656

5757
(define delim
5858
(string-append "$|"

Diff for: main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ int main(int argc, char** argv) {
2727
}
2828

2929
void error() {
30-
printf("err");
30+
printf("err\n");
3131
exit(1);
3232
}
3333

0 commit comments

Comments
 (0)