Skip to content

Commit d160751

Browse files
committed
crook
1 parent e4b5c44 commit d160751

File tree

14 files changed

+633
-169
lines changed

14 files changed

+633
-169
lines changed

iniquity-plus/ast.rkt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
;; | (App Id (Listof Expr))
3131
;; | (Apply Id (Listof Expr) Expr)
3232

33+
;; type ClosedExpr = { e ∈ Expr | e contains no free variables }
34+
3335
;; type Id = Symbol
3436
;; type Datum = Integer
3537
;; | Boolean

iniquity-plus/compile-stdin.rkt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
;; emit asm code on stdout
1111
(define (main)
1212
(read-line) ; ignore #lang racket line
13-
(asm-display (compile (apply parse (read-all)))))
13+
(asm-display (compile
14+
(apply parse-closed (read-all)))))
1415

iniquity-plus/interp-stdin.rkt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
;; print result on stdout
1010
(define (main)
1111
(read-line) ; ignore #lang racket line
12-
(println (interp (apply parse (read-all)))))
12+
(println (interp
13+
(apply parse-closed (read-all)))))
1314

iniquity-plus/parse.rkt

Lines changed: 219 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,233 @@
11
#lang racket
2-
(provide parse parse-e parse-define)
2+
(provide parse parse-closed parse-e parse-define)
33
(require "ast.rkt")
44

5-
;; S-Expr ... -> Prog
6-
(define (parse . s)
7-
(match s
8-
[(cons (and (cons 'define _) d) s)
9-
(match (apply parse s)
10-
[(Prog ds e)
11-
(Prog (cons (parse-define d) ds) e)])]
12-
[(cons e '()) (Prog '() (parse-e e))]
13-
[_ (error "program parse error")]))
14-
15-
;; S-Expr -> Defn
5+
;; [Listof S-Expr] -> Prog
6+
(define (parse . ss)
7+
(match (parse-prog ss (parse-defn-names ss) '() '() '())
8+
[(list _ _ p) p]))
9+
10+
;; [Listof S-Expr] -> ClosedProg
11+
(define (parse-closed . ss)
12+
(match (parse-prog ss (parse-defn-names ss) '() '() '())
13+
[(list '() '() p) p]
14+
[(list ys gs p) (error "undefined identifiers" (append ys gs))]))
15+
16+
;; S-Expr -> Expr
17+
;; Parse a (potentially open) expression
18+
(define (parse-e s)
19+
(match (parse-e/acc s '() '() '() '())
20+
[(list _ _ e) e]))
21+
22+
;; S-Expr -> Expr
23+
;; Parse a (potentially open) definition
1624
(define (parse-define s)
25+
(match (parse-define/acc s '() '() '() '())
26+
[(list _ _ d) d]))
27+
28+
;; S-Expr -> r:[Listof Id]
29+
;; where: (distinct? r)
30+
;; Extracts defined function names from given program-like s-expr
31+
;; Does not fully parse definition
32+
;; Example:
33+
;; (parse-defn-names '((define (f x) x) (define (g y) y) 1) -> '(f g)
34+
(define (parse-defn-names ss)
35+
(define (rec ss fs)
36+
(match ss
37+
[(list s) fs]
38+
[(cons (cons 'define sd) sr)
39+
(match (parse-defn-name sd)
40+
[f (if (memq f fs)
41+
(error "duplicate definition" f)
42+
(rec sr (cons f fs)))])]
43+
[_ (error "parse error")]))
44+
(rec ss '()))
45+
46+
(define (parse-defn-name s)
47+
(match s
48+
[(cons (cons (? symbol? f) _) _) f]
49+
[(cons (? symbol? f) _) f]
50+
[_ (error "parse error")]))
51+
52+
;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Prog)
53+
;; s: program shaped s-expr to be parsed
54+
;; fs: defined function names
55+
;; xs: bound variables
56+
;; ys: free variables
57+
;; gs: undefined function names
58+
;; returns list of free variables, undefined function names, and parse of program
59+
(define (parse-prog s fs xs ys gs)
60+
(match s
61+
[(list s)
62+
(match (parse-e/acc s fs xs ys gs)
63+
[(list ys gs e)
64+
(list ys gs (Prog '() e))])]
65+
[(cons s ss)
66+
(match (parse-define/acc s fs xs ys gs)
67+
[(list ys gs (and d (Defn f _)))
68+
(match (parse-prog ss (cons f fs) xs ys gs)
69+
[(list ys gs (Prog ds e))
70+
(list ys gs (Prog (cons d ds) e))])])]))
71+
72+
73+
;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Defn)
74+
;; s: definition shaped s-expr to be parsed
75+
;; fs: defined function names
76+
;; xs: bound variables
77+
;; ys: free variables
78+
;; gs: undefined function names
79+
;; returns list of free variables, undefined function names, and parse of definition
80+
(provide (all-defined-out))
81+
(define (parse-define/acc s fs xs ys gs)
82+
(match s
83+
[(list 'define (? symbol? f) (cons 'case-lambda sr))
84+
(match (parse-case-lambda/acc sr fs xs ys gs)
85+
[(list ys gs fun)
86+
(list ys gs (Defn f fun))])]
87+
[(cons 'define (cons (cons (? symbol? f) ps) sr))
88+
(match (parse-define-plain-or-rest-fun/acc (cons ps sr) fs xs ys gs)
89+
[(list ys gs fun)
90+
(list ys gs (Defn f fun))])]
91+
[_ (error "parse error")]))
92+
93+
(define (parse-case-lambda/acc s fs xs ys gs)
94+
(match s
95+
['() (list ys gs (FunCase '()))]
96+
[(cons s sr)
97+
(match (parse-define-plain-or-rest-fun/acc s fs xs ys gs)
98+
[(list ys gs l)
99+
(match (parse-case-lambda/acc sr fs xs ys gs)
100+
[(list ys gs (FunCase ls))
101+
(list ys gs (FunCase (cons l ls)))])])]
102+
[_ (error "parse error")]))
103+
104+
(define (parse-define-plain-or-rest-fun/acc s fs xs ys gs)
105+
(match s
106+
[(list '() s)
107+
(match (parse-e/acc s fs xs ys gs)
108+
[(list ys gs e)
109+
(list ys gs (FunPlain '() e))])]
110+
[(list (? symbol? r) s)
111+
(match (parse-e/acc s fs (cons r xs) ys gs)
112+
[(list ys gs e)
113+
(list ys gs (FunRest '() r e))])]
114+
[(list (cons (? symbol? x) r) s)
115+
(match (parse-define-plain-or-rest-fun/acc (list r s) fs (cons x xs) ys gs)
116+
[(list ys gs (FunPlain xs e))
117+
(list ys gs (FunPlain (cons x xs) e))]
118+
[(list ys gs (FunRest xs r e))
119+
(list ys gs (FunRest (cons x xs) r e))])]
120+
[_ (error "parse error")]))
121+
122+
;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Expr)
123+
;; s: expression shaped s-expr to be parsed
124+
;; fs: defined function names
125+
;; xs: bound variables
126+
;; ys: free variables
127+
;; gs: undefined function names
128+
;; returns list of free variables, undefined function names, and parse of expression
129+
(define (parse-e/acc s fs xs ys gs)
130+
(define (rec s xs ys gs)
131+
(define ns (append fs xs))
132+
(match s
133+
[(and 'eof (? (not-in ns)))
134+
(list ys gs (Eof))]
135+
[(? datum?)
136+
(list ys gs (Lit s))]
137+
[(list 'quote (list))
138+
(list ys gs (Lit '()))]
139+
[(? symbol? (? (not-in fs)))
140+
(if (memq s xs)
141+
(list ys gs (Var s))
142+
(list (cons s ys) gs (Var s)))]
143+
[(list-rest (? symbol? (? (not-in ns) k)) sr)
144+
(match k
145+
['let
146+
(match sr
147+
[(list (list (list (? symbol? x) s1)) s2)
148+
(match (rec s1 xs ys gs)
149+
[(list ys gs e1)
150+
(match (rec s2 (cons x xs) ys gs)
151+
[(list ys gs e2)
152+
(list ys gs (Let x e1 e2))])])]
153+
[_ (error "let: bad syntax" s)])]
154+
['apply
155+
(match sr
156+
[(list-rest (? symbol? f) sr)
157+
(parse-apply/acc sr f fs xs ys (if (memq f fs) gs (cons f gs)))])]
158+
[_
159+
(match (parse-es/acc sr fs xs ys gs)
160+
[(list ys gs es)
161+
(match (cons k es)
162+
[(list (? op0? o))
163+
(list ys gs (Prim0 o))]
164+
[(list (? op1? o) e1)
165+
(list ys gs (Prim1 o e1))]
166+
[(list (? op2? o) e1 e2)
167+
(list ys gs (Prim2 o e1 e2))]
168+
[(list (? op3? o) e1 e2 e3)
169+
(list ys gs (Prim3 o e1 e2 e3))]
170+
[(list 'begin e1 e2)
171+
(list ys gs (Begin e1 e2))]
172+
[(list 'if e1 e2 e3)
173+
(list ys gs (If e1 e2 e3))]
174+
[(list-rest g es)
175+
(list ys (cons g gs) (App g es))])])])]
176+
[(list-rest (? symbol? g) sr)
177+
(match (parse-es/acc sr fs xs ys gs)
178+
[(list ys s es)
179+
(list ys (if (memq g fs) gs (cons g gs)) (App g es))])]
180+
[_
181+
(error "parse error" s)]))
182+
(rec s xs ys gs))
183+
184+
;; S-Expr Id [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Apply)
185+
(define (parse-apply/acc s f fs xs ys gs)
186+
(match s
187+
[(list s)
188+
(match (parse-e/acc s fs xs ys gs)
189+
[(list ys gs e)
190+
(list ys gs (Apply f '() e))])]
191+
[(cons s sr)
192+
(match (parse-e/acc s fs xs ys gs)
193+
[(list ys gs e)
194+
(match (parse-apply/acc sr f fs xs ys gs)
195+
[(list ys gs (Apply f es e0))
196+
(list ys gs (Apply f (cons e es) e0))])])]))
197+
198+
;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] [Listof Expr])
199+
;; s: list of expressions shaped s-expr to be parsed
200+
;; fs: defined function names
201+
;; xs: bound variables
202+
;; ys: free variables
203+
;; gs: undefined function names
204+
;; returns list of free variables, undefined function names, and list of parsed expressions
205+
(define (parse-es/acc s fs xs ys gs)
17206
(match s
18-
[(list 'define (? symbol? f)
19-
(cons 'case-lambda cs))
20-
(Defn f (FunCase (parse-case-lambda-clauses cs)))]
21-
[(list 'define (cons (? symbol? f) xs) e)
22-
(if (all symbol? xs)
23-
(Defn f (parse-param-list xs e))
24-
(error "parse definition error"))]
25-
[_ (error "Parse defn error" s)]))
26-
27-
;; like andmap, but work on improper lists too
207+
['() (list ys gs '())]
208+
[(cons s ss)
209+
(match (parse-e/acc s fs xs ys gs)
210+
[(list ys gs e)
211+
(match (parse-es/acc ss fs xs ys gs)
212+
[(list ys gs es)
213+
(list ys gs (cons e es))])])]
214+
[_ (error "parse error")]))
215+
216+
(define (distinct? xs)
217+
(not (check-duplicates xs)))
218+
219+
;; like andmap, but works on improper lists too
28220
(define (all p? xs)
29221
(match xs
30222
['() #t]
31223
[(cons x xs) (and (p? x) (all p? xs))]
32224
[x (p? x)]))
33225

34-
;; S-Expr -> [Listof FunCaseClause]
35-
(define (parse-case-lambda-clauses cs)
36-
(match cs
37-
['() '()]
38-
[(cons c cs)
39-
(cons (parse-case-lambda-clause c)
40-
(parse-case-lambda-clauses cs))]
41-
[_
42-
(error "parse case-lambda error")]))
43-
44-
;; S-Expr -> FunRest
45-
(define (parse-case-lambda-clause c)
46-
(match c
47-
[(list (? symbol? x) e)
48-
(FunRest '() x (parse-e e))]
49-
[(list xs e)
50-
(parse-param-list xs e)]))
51-
52-
;; S-Expr S-Expr -> FunPlain or FunRest
53-
(define (parse-param-list xs e)
54-
(match xs
55-
['() (FunPlain '() (parse-e e))]
56-
[(cons x xs)
57-
(match (parse-param-list xs e)
58-
[(FunPlain xs e) (FunPlain (cons x xs) e)]
59-
[(FunRest xs y e) (FunRest (cons x xs) y e)])]
60-
[(? symbol? xs)
61-
(FunRest '() xs (parse-e e))]
62-
[_
63-
(error "parse parameter list error")]))
64-
65-
;; S-Expr -> Expr
66-
(define (parse-e s)
67-
(match s
68-
[(? datum?) (Lit s)]
69-
['eof (Eof)]
70-
[(? symbol?) (Var s)]
71-
[(list 'quote (list)) (Lit '())]
72-
[(list (? op0? p0)) (Prim0 p0)]
73-
[(list (? op1? p1) e) (Prim1 p1 (parse-e e))]
74-
[(list (? op2? p2) e1 e2) (Prim2 p2 (parse-e e1) (parse-e e2))]
75-
[(list (? op3? p3) e1 e2 e3)
76-
(Prim3 p3 (parse-e e1) (parse-e e2) (parse-e e3))]
77-
[(list 'begin e1 e2)
78-
(Begin (parse-e e1) (parse-e e2))]
79-
[(list 'if e1 e2 e3)
80-
(If (parse-e e1) (parse-e e2) (parse-e e3))]
81-
[(list 'let (list (list (? symbol? x) e1)) e2)
82-
(Let x (parse-e e1) (parse-e e2))]
83-
[(cons 'apply (cons (? symbol? f) es))
84-
(parse-apply f es)]
85-
[(cons (? symbol? f) es)
86-
(App f (map parse-e es))]
87-
[_ (error "Parse error" s)]))
88-
89-
;; Id S-Expr -> Expr
90-
(define (parse-apply f es)
91-
(match es
92-
[(list e) (Apply f '() (parse-e e))]
93-
[(cons e es)
94-
(match (parse-apply f es)
95-
[(Apply f es e0)
96-
(Apply f (cons (parse-e e) es) e0)])]
97-
[_ (error "parse apply error")]))
226+
;; [Listof Any] -> (Any -> Boolean)
227+
(define (not-in m)
228+
(λ (x) (not (memq x m))))
229+
(define (in m)
230+
(λ (x) (memq x m)))
98231

99232

100233
;; Any -> Boolean

iniquity-plus/test/compile.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
(require "../exec.rkt")
55
(require "../exec-io.rkt")
66
(require "test-runner.rkt")
7-
(test (λ p (exec (apply parse p))))
8-
(test/io (λ (in . p) (exec/io (apply parse p) in)))
7+
(test (λ p (exec (apply parse-closed p))))
8+
(test/io (λ (in . p) (exec/io (apply parse-closed p) in)))
99

iniquity-plus/test/interp.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
(require "../interp-io.rkt")
44
(require "../parse.rkt")
55
(require "test-runner.rkt")
6-
(test (λ p (interp (apply parse p))))
7-
(test/io (λ (in . p) (interp/io (apply parse p) in)))
6+
(test (λ p (interp (apply parse-closed p))))
7+
(test/io (λ (in . p) (interp/io (apply parse-closed p) in)))
88

0 commit comments

Comments
 (0)