Skip to content

Commit 150aba0

Browse files
committed
New AST for jig
1 parent 83cb088 commit 150aba0

4 files changed

Lines changed: 284 additions & 59 deletions

File tree

www/notes/jig/ast.rkt

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#lang racket
2+
(provide (all-defined-out))
3+
4+
;; type Prog = [FunDef] Expr
5+
6+
;; type FunDef = Variable [Variable] Expr
7+
8+
;; type Expr =
9+
;; | Integer
10+
;; | Boolean
11+
;; | Character
12+
;; | Variable
13+
;; | Prim1 Expr
14+
;; | Prim2 Expr Expr
15+
;; | App Variable [Expr]
16+
;; | If Expr Expr Expr
17+
;; | Let (Binding list) Expr
18+
;; | Nil
19+
20+
;; type Prim1 = 'add1 | 'sub1 | 'zero? | box | unbox | car | cdr
21+
;; type Prim2 = '+ | '- | cons
22+
23+
;; type Binding = Variable Expr
24+
25+
;; type Variable = Symbol (except 'add1 'sub1 'if, etc.)
26+
27+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28+
;;;;;; The represenation of top-level programs
29+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30+
31+
(struct prog (ds e) #:transparent)
32+
33+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34+
;;;;;; The represenation of a function definition
35+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36+
37+
;; A FunDef has a symbol for the function's name,
38+
;; a list of symbols representing the names of the function's
39+
;; arguments, and one expression that forms the body of the function.
40+
(struct fundef (name args body) #:transparent)
41+
42+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
43+
;;;;;; The Expr data structure
44+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45+
46+
;; An Expr can be viewed as having 'kinds' of nodes.
47+
;;
48+
;; * The nodes that represnt an expression themselves
49+
;;
50+
;; * The nodes that are part of an expression, but no an expression themselves
51+
52+
;; The below are the former:
53+
54+
(struct int-e (i) #:transparent)
55+
(struct bool-e (b) #:transparent)
56+
(struct char-e (c) #:transparent)
57+
(struct var-e (v) #:transparent)
58+
(struct prim-e (p es) #:transparent)
59+
(struct app-e (f es) #:transparent) ; <- new for Iniquity
60+
(struct if-e (e t f) #:transparent)
61+
(struct let-e (bs b) #:transparent)
62+
(struct nil-e () #:transparent)
63+
64+
;; The next is the latter:
65+
66+
;; A binding holds a symbol representing the bound variable and
67+
;; Expr that represents the value that will be bound to that variable
68+
(struct binding (v e) #:transparent)
69+
70+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
71+
;;;;;; AST utility functions (predicates)
72+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
73+
74+
(define unops '(add1 sub1 zero? box unbox empty? car cdr))
75+
(define biops '(+ - cons))
76+
77+
;; Any -> Boolean
78+
(define (prim? x)
79+
(and (symbol? x)
80+
(memq x (append unops biops))))
81+
82+
;; Any -> Boolean
83+
(define (biop? x)
84+
(and (symbol? x)
85+
(memq x biops)))
86+
87+
;; Any -> Boolean
88+
(define (unop? x)
89+
(and (symbol? x)
90+
(memq x unops)))
91+
92+
(define (value? v)
93+
(or (int-e? v)
94+
(bool-e? v)))
95+
96+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
97+
;;;;;; AST utility functions (getters)
98+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
99+
100+
;; It will sometimes be useful to get the list of all the variables that are
101+
;; introduced by a `let`
102+
;; [Binding] -> [Symbol]
103+
(define (get-vars bs)
104+
(match bs
105+
['() '()]
106+
[(cons (binding v _) bs) (cons v (get-vars bs))]))
107+
108+
;; Get all of the _definitions_ from a list of bindings
109+
;; [Binding] -> [Expr]
110+
(define (get-defs bs)
111+
(match bs
112+
['() '()]
113+
[(cons (binding _ def) bs) (cons def (get-defs bs))]))
114+
115+
116+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
117+
;;;;;; AST utility functions (printers)
118+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
119+
120+
;; We have switched to using `#:transparent` above, so this should only be
121+
;; necessary if you're desperate when debugging :'(
122+
123+
;; Given a Program, construct an sexpr that has the same shape
124+
(define (prog-debug p)
125+
(match p
126+
[(prog ds e) `(prog ,(map fundef-debug ds) ,(ast-debug e))]))
127+
128+
;; Given a FunDef, construct an sexpr that has the same shape
129+
(define (fundef-debug def)
130+
(match def
131+
[(fundef name args body) `(fundef ,name ,args ,(ast-debug body))]))
132+
133+
;; Given an AST, construct an sexpr that has the same shape
134+
(define (ast-debug a)
135+
(match a
136+
[(int-e i) `(int-e ,i)]
137+
[(bool-e b) `(bool-e ,b)]
138+
[(char-e c) `(char-e ,c)]
139+
[(var-e v) `(var-e ,v)]
140+
[(nil-e) ''()]
141+
[(prim-e p es) `(prim-e ,p ,@(map ast-debug es))]
142+
[(app-e f es) `(app-e ,f ,@(map ast-debug es))]
143+
[(if-e e t f) `(if-e ,(ast-debug e)
144+
,(ast-debug t)
145+
,(ast-debug f))]
146+
[(let-e bs b) `(let-e ,(binding-debug bs) ,(ast-debug b))]))
147+
148+
(define (binding-debug bnds)
149+
(match bnds
150+
['() '()]
151+
[(cons (binding v e) bnds) `((,v ,(ast-debug e)) ,@(binding-debug bnds))]))

www/notes/jig/compile.rkt

Lines changed: 61 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#lang racket
22
(provide (all-defined-out))
33

4+
(require "ast.rkt")
5+
46
;; An immediate is anything ending in #b000
57
;; All other tags in mask #b111 are pointers
68

@@ -26,22 +28,15 @@
2628
;; end in #b000 and we tag with #b001 for boxes, etc.
2729

2830
;; type CEnv = (Listof (Maybe Variable))
29-
;; type Imm = Integer | Boolean | Char | ''()
30-
31-
;; type Prog =
32-
;; | Expr
33-
;; | `(begin ,@(Listof (define (,Variable ,@(Listof Variable)) ,Expr))
34-
;; ,Expr)
3531

3632
;; Prog -> Asm
3733
(define (compile p)
3834
(match p
39-
[(list 'begin `(define (,fs . ,xss) ,es) ... e0)
40-
(let ((ds (compile-defines fs xss es))
41-
(c0 (compile-entry e0)))
35+
[(prog defs e)
36+
(let ((ds (compile-defines defs))
37+
(c0 (compile-entry e)))
4238
`(,@c0
43-
,@ds))]
44-
[e (compile-entry e)]))
39+
,@ds))]))
4540

4641
;; Expr -> Asm
4742
;; Compile e as the entry point
@@ -57,28 +52,28 @@
5752
;; Compile an expression in tail position
5853
(define (compile-tail-e e c)
5954
(match e
60-
[(? symbol? x) (compile-variable x c)]
61-
[(? imm? i) (compile-imm i)]
62-
[`(box ,e0) (compile-box e0 c)]
63-
[`(unbox ,e0) (compile-unbox e0 c)]
64-
[`(cons ,e0 ,e1) (compile-cons e0 e1 c)]
65-
[`(car ,e0) (compile-car e0 c)]
66-
[`(cdr ,e0) (compile-cdr e0 c)]
67-
[`(add1 ,e0) (compile-add1 e0 c)]
68-
[`(sub1 ,e0) (compile-sub1 e0 c)]
69-
[`(zero? ,e0) (compile-zero? e0 c)]
70-
[`(empty? ,e0) (compile-empty? e0 c)]
71-
[`(if ,e0 ,e1 ,e2) (compile-tail-if e0 e1 e2 c)]
72-
[`(+ ,e0 ,e1) (compile-+ e0 e1 c)]
73-
[`(let ((,x ,e0)) ,e1) (compile-tail-let x e0 e1 c)]
74-
[`(,f . ,es) (compile-tail-call f es c)]))
55+
[(var-e v) (compile-variable v c)]
56+
[(? imm? i) (compile-imm i)]
57+
[(prim-e (? prim? p) es) (compile-prim p es c)]
58+
[(if-e p t f) (compile-tail-if p t f c)]
59+
[(let-e (list b) body) (compile-tail-let b body c)]
60+
[(app-e f es) (compile-tail-call f es c)]))
7561

7662
;; Expr CEnv -> Asm
7763
;; Compile an expression in non-tail position
7864
(define (compile-e e c)
7965
(match e
80-
[(? symbol? x) (compile-variable x c)]
81-
[(? imm? i) (compile-imm i)]
66+
[(var-e v) (compile-variable v c)]
67+
[(? imm? i) (compile-imm i)]
68+
[(prim-e (? prim? p) es) (compile-prim p es c)]
69+
[(if-e p t f) (compile-if p t f c)]
70+
[(let-e (list b) body) (compile-let b body c)]
71+
[(app-e f es) (compile-call f es c)]))
72+
73+
;; Our current set of primitive operations require no function calls,
74+
;; so there's no difference between tail and non-tail call positions
75+
(define (compile-prim p es c)
76+
(match (cons p es)
8277
[`(box ,e0) (compile-box e0 c)]
8378
[`(unbox ,e0) (compile-unbox e0 c)]
8479
[`(cons ,e0 ,e1) (compile-cons e0 e1 c)]
@@ -88,10 +83,9 @@
8883
[`(sub1 ,e0) (compile-sub1 e0 c)]
8984
[`(zero? ,e0) (compile-zero? e0 c)]
9085
[`(empty? ,e0) (compile-empty? e0 c)]
91-
[`(if ,e0 ,e1 ,e2) (compile-if e0 e1 e2 c)]
9286
[`(+ ,e0 ,e1) (compile-+ e0 e1 c)]
93-
[`(let ((,x ,e0)) ,e1) (compile-let x e0 e1 c)]
94-
[`(,f . ,es) (compile-call f es c)]))
87+
[_ (error
88+
(format "prim applied to wrong number of args: ~a ~a" p es))]))
9589

9690
;; Variable (Listof Expr) CEnv -> Asm
9791
;; Statically know the function we're calling
@@ -132,22 +126,24 @@
132126
,@cs))]))
133127

134128
;; Variable (Listof Variable) Expr -> Asm
135-
(define (compile-define f xs e0)
136-
(let ((c0 (compile-tail-e e0 (reverse xs))))
137-
`(,(symbol->label f)
138-
,@c0
139-
ret)))
129+
(define (compile-define def)
130+
(match def
131+
[(fundef name args body)
132+
(let ((c0 (compile-e body (reverse args))))
133+
`(,(symbol->label name)
134+
,@c0
135+
ret))]))
140136

141137
;; (Listof Variable) (Listof (Listof Variable)) (Listof Expr) -> Asm
142-
(define (compile-defines fs xss es)
143-
(append-map compile-define fs xss es))
138+
(define (compile-defines defs)
139+
(append-map compile-define defs))
144140

145141
;; Any -> Boolean
146142
(define (imm? x)
147-
(or (integer? x)
148-
(boolean? x)
149-
(char? x)
150-
(equal? ''() x)))
143+
(or (int-e? x)
144+
(bool-e? x)
145+
(char-e? x)
146+
(nil-e? x)))
151147

152148
;; Imm -> Asm
153149
(define (compile-imm i)
@@ -156,10 +152,11 @@
156152
;; Imm -> Integer
157153
(define (imm->bits i)
158154
(match i
159-
[(? integer? i) (arithmetic-shift i imm-shift)]
160-
[(? char? c) (+ (arithmetic-shift (char->integer c) imm-shift) imm-type-char)]
161-
[(? boolean? b) (if b imm-val-true imm-val-false)]
162-
[''() imm-type-empty]))
155+
[(int-e i) (arithmetic-shift i imm-shift)]
156+
[(char-e c) (+ (arithmetic-shift (char->integer c) imm-shift) imm-type-char)]
157+
[(bool-e b) (if b imm-val-true imm-val-false)]
158+
[(nil-e) imm-type-empty]))
159+
163160

164161
;; Variable CEnv -> Asm
165162
(define (compile-variable x c)
@@ -285,20 +282,26 @@
285282
,l1)))
286283

287284
;; Variable Expr Expr CEnv -> Asm
288-
(define (compile-tail-let x e0 e1 c)
289-
(let ((c0 (compile-e e0 c))
290-
(c1 (compile-tail-e e1 (cons x c))))
291-
`(,@c0
292-
(mov (offset rsp ,(- (add1 (length c)))) rax)
293-
,@c1)))
285+
(define (compile-tail-let b e1 c)
286+
(match b
287+
[(binding v def)
288+
(let ((c0 (compile-e def c))
289+
(c1 (compile-tail-e e1 (cons v c))))
290+
`(,@c0
291+
(mov (offset rsp ,(- (add1 (length c)))) rax)
292+
,@c1))]
293+
[_ (error "Compile-let can only handle bindings")]))
294294

295295
;; Variable Expr Expr CEnv -> Asm
296-
(define (compile-let x e0 e1 c)
297-
(let ((c0 (compile-e e0 c))
298-
(c1 (compile-e e1 (cons x c))))
299-
`(,@c0
300-
(mov (offset rsp ,(- (add1 (length c)))) rax)
301-
,@c1)))
296+
(define (compile-let b e1 c)
297+
(match b
298+
[(binding v def)
299+
(let ((c0 (compile-e def c))
300+
(c1 (compile-e e1 (cons v c))))
301+
`(,@c0
302+
(mov (offset rsp ,(- (add1 (length c)))) rax)
303+
,@c1))]
304+
[_ (error "Compile-let can only handle bindings")]))
302305

303306
;; Expr Expr CEnv -> Asm
304307
(define (compile-+ e0 e1 c)

0 commit comments

Comments
 (0)