-
Notifications
You must be signed in to change notification settings - Fork 0
/
inherit-parse.rkt~
137 lines (120 loc) · 4.19 KB
/
inherit-parse.rkt~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#lang plait
(require "class.rkt"
"inherit.rkt")
(module+ test
(print-only-errors #t))
;; ----------------------------------------
(define (parse-class [s : S-Exp]) : (Symbol * ClassI)
(cond
[(s-exp-match? `{class SYMBOL extends SYMBOL {ANY ...} ANY ...} s)
(values (s-exp->symbol (second (s-exp->list s)))
(classI
(s-exp->symbol (fourth (s-exp->list s)))
(map parse-field
(s-exp->list (fourth (rest (s-exp->list s)))))
(map parse-method
(rest (rest (rest (rest (rest (s-exp->list s)))))))))]
[else (error 'parse-class "invalid input")]))
(define (parse-field [s : S-Exp]) : Symbol
(cond
[(s-exp-match? `SYMBOL s)
(s-exp->symbol s)]
[else (error 'parse-field "invalid input")]))
(define (parse-method [s : S-Exp]) : (Symbol * ExpI)
(cond
[(s-exp-match? `[SYMBOL {arg} ANY] s)
(values (s-exp->symbol (first (s-exp->list s)))
(parse (third (s-exp->list s))))]
[else (error 'parse-method "invalid input")]))
(define (parse [s : S-Exp]) : ExpI
(cond
[(s-exp-match? `NUMBER s) (numI (s-exp->number s))]
[(s-exp-match? `arg s) (argI)]
[(s-exp-match? `this s) (thisI)]
[(s-exp-match? `{+ ANY ANY} s)
(plusI (parse (second (s-exp->list s)))
(parse (third (s-exp->list s))))]
[(s-exp-match? `{* ANY ANY} s)
(multI (parse (second (s-exp->list s)))
(parse (third (s-exp->list s))))]
[(s-exp-match? `{new SYMBOL ANY ...} s)
(newI (s-exp->symbol (second (s-exp->list s)))
(map parse (rest (rest (s-exp->list s)))))]
[(s-exp-match? `{get ANY SYMBOL} s)
(getI (parse (second (s-exp->list s)))
(s-exp->symbol (third (s-exp->list s))))]
[(s-exp-match? `{send ANY SYMBOL ANY} s)
(sendI (parse (second (s-exp->list s)))
(s-exp->symbol (third (s-exp->list s)))
(parse (fourth (s-exp->list s))))]
[(s-exp-match? `{super SYMBOL ANY} s)
(superI (s-exp->symbol (second (s-exp->list s)))
(parse (third (s-exp->list s))))]
[else (error 'parse "invalid input")]))
(module+ test
(test (parse `0)
(numI 0))
(test (parse `arg)
(argI))
(test (parse `this)
(thisI))
(test (parse `{+ 1 2})
(plusI (numI 1) (numI 2)))
(test (parse `{* 1 2})
(multI (numI 1) (numI 2)))
(test (parse `{new Posn 1 2})
(newI 'Posn (list (numI 1) (numI 2))))
(test (parse `{get 1 x})
(getI (numI 1) 'x))
(test (parse `{send 1 m 2})
(sendI (numI 1) 'm (numI 2)))
(test (parse `{super m 1})
(superI 'm (numI 1)))
(test/exn (parse `x)
"invalid input")
(test (parse-field `x)
'x)
(test/exn (parse-field `{x 1})
"invalid input")
(test (parse-method `[m {arg} this])
(values 'm (thisI)))
(test/exn (parse-method `[m {arg} 1 2])
"invalid input")
(test (parse-class `{class Posn3D extends Posn
{x y z}
[m1 {arg} arg]
[m2 {arg} this]})
(values 'Posn3D
(classI 'Posn
(list 'x 'y 'z)
(list (values 'm1 (argI))
(values 'm2 (thisI))))))
(test/exn (parse-class `{class})
"invalid input"))
;; ----------------------------------------
(define (interp-prog [classes : (Listof S-Exp)] [a : S-Exp]) : S-Exp
(let ([v (interp-i (parse a)
(map parse-class classes))])
(type-case Value v
[(numV n) (number->s-exp n)]
[(objV class-name field-vals) `object])))
(module+ test
(test (interp-prog
(list
`{class Empty extends Object
{}})
`{new Empty})
`object)
(test (interp-prog
(list
`{class Posn extends Object
{x y}
[mdist {arg} {+ {get this x} {get this y}}]
[addDist {arg} {+ {send arg mdist 0}
{send this mdist 0}}]}
`{class Posn3D extends Posn
{z}
[mdist {arg} {+ {get this z}
{super mdist arg}}]})
`{send {new Posn3D 5 3 1} addDist {new Posn 2 7}})
`18))