git @ Cat's Eye Technologies Castile / 45c1bd7
Refactoring: move modules around, avoid late import in TypeChecker. --HG-- rename : src/castile/compiler.py => src/castile/backends/javascript.py rename : src/castile/types.py => src/castile/checker.py catseye 12 years ago
6 changed file(s) with 470 addition(s) and 471 deletion(s). Raw diff Collapse all Expand all
0 from castile.types import Void
1
2 OPS = {
3 'and': '&&',
4 'or': '||',
5 '==': '===',
6 }
7
8
9 class Compiler(object):
10 def __init__(self, out):
11 self.out = out
12
13 def commas(self, asts, sep=','):
14 if asts:
15 for child in asts[:-1]:
16 self.compile(child)
17 self.out.write(sep)
18 self.compile(asts[-1])
19
20 def compile(self, ast):
21 if ast.type == 'Program':
22 self.out.write("""\
23 /* AUTOMATICALLY GENERATED EDIT AT OWN RISK */
24
25 var print = function(s) { console.log(s); }
26 var len = function(s) { return s.length; }
27 var concat = function(s1,s2) { return s1 + s2; }
28 var substr = function(s,p,k) { return s.substr(p, k); }
29
30 var repr = function(o) {
31 if (typeof o === "string") {
32 return "'" + o + "'";
33 } else if (o === true) {
34 return "True";
35 } else if (o === false) {
36 return "False";
37 } else if (o === undefined) {
38 return "";
39 } else if (typeof o === "object") {
40 var s = "(";
41 for (var i = 0; i < o.length; i++) {
42 s += repr(o[i]);
43 if (i != o.length - 1) { s += ', '; }
44 }
45 s += ")";
46 return s;
47 } else {
48 return o;
49 }
50 }
51
52 """)
53 for child in ast.children:
54 self.compile(child)
55 self.out.write("""\
56
57 var result = main();
58 print(repr(result));
59 """)
60 elif ast.type == 'Defn':
61 self.out.write('%s = ' % ast.value)
62 self.compile(ast.children[0])
63 self.out.write(';\n')
64 elif ast.type in ('StructDefn', 'Forward'):
65 pass
66 elif ast.type == 'FunLit':
67 self.out.write('function(')
68 self.compile(ast.children[0])
69 self.out.write(')\n')
70 self.compile(ast.children[1])
71 elif ast.type == 'Args':
72 self.commas(ast.children)
73 elif ast.type == 'Arg':
74 self.out.write(ast.value)
75 elif ast.type == 'Block':
76 # typechecker assigned ast.t the type of this block
77 # typechecker assigned value 'function body' if it is a fn bd
78 self.out.write('{')
79 if not ast.children:
80 if ast.value == 'function body':
81 self.out.write('return undefined;')
82 elif ast.t == Void():
83 for child in ast.children:
84 self.compile(child)
85 self.out.write(';\n')
86 if ast.value == 'function body':
87 self.out.write('return undefined;')
88 elif ast.children[-1].type == 'If':
89 for child in ast.children:
90 self.compile(child)
91 self.out.write(';\n')
92 if ast.value == 'function body':
93 self.out.write('return result;')
94 else:
95 for child in ast.children[:-1]:
96 self.compile(child)
97 self.out.write(';\n')
98 if ast.value == 'function body':
99 self.out.write('return ')
100 self.compile(ast.children[-1])
101 self.out.write(';\n')
102 else:
103 self.out.write('result = ')
104 self.compile(ast.children[-1])
105 self.out.write(';\n')
106 self.out.write('}')
107 elif ast.type == 'VarDecl':
108 self.out.write('var %s = ' % ast.value)
109 self.compile(ast.children[0])
110 elif ast.type == 'While':
111 self.out.write('while (')
112 self.compile(ast.children[0])
113 self.out.write(')')
114 self.compile(ast.children[1])
115 elif ast.type == 'Op':
116 self.out.write('(')
117 self.compile(ast.children[0])
118 self.out.write(' %s ' % OPS.get(ast.value, ast.value))
119 self.compile(ast.children[1])
120 self.out.write(')')
121 elif ast.type == 'VarRef':
122 self.out.write(ast.value)
123 elif ast.type == 'FunCall':
124 self.compile(ast.children[0])
125 self.out.write('(')
126 self.commas(ast.children[1:])
127 self.out.write(')')
128 elif ast.type == 'If':
129 if ast.children[1].t == Void():
130 self.out.write('if(')
131 self.compile(ast.children[0])
132 self.out.write(')')
133 if len(ast.children) == 3: # if-else
134 self.compile(ast.children[1])
135 self.out.write(' else ')
136 self.compile(ast.children[2])
137 else: # just-if
138 self.compile(ast.children[1])
139 else:
140 # this assumes you return the result from the current
141 # function, but this assumption is safe, because if you
142 # didn't, it wouldn't typecheck.
143 self.out.write('{ var result; if(')
144 self.compile(ast.children[0])
145 self.out.write(')')
146 self.compile(ast.children[1])
147 self.out.write(' else ')
148 self.compile(ast.children[2])
149 self.out.write('return result; }')
150 elif ast.type == 'Return':
151 self.out.write('return ')
152 self.compile(ast.children[0])
153 elif ast.type == 'Do':
154 self.compile(ast.children[0])
155 elif ast.type == 'Not':
156 self.out.write('!(')
157 self.compile(ast.children[0])
158 self.out.write(')')
159 elif ast.type == 'None':
160 self.out.write('null')
161 elif ast.type == 'IntLit':
162 self.out.write(str(ast.value))
163 elif ast.type == 'StrLit':
164 self.out.write("'%s'" % ast.value)
165 elif ast.type == 'Assignment':
166 self.compile(ast.children[0])
167 self.out.write(' = ')
168 self.compile(ast.children[1])
169 elif ast.type == 'Make':
170 self.out.write('[')
171 self.commas(ast.children[1:])
172 self.out.write(']')
173 elif ast.type == 'Index':
174 self.compile(ast.children[0])
175 # ast.value was converted from a field name to an index by
176 # the typechecker.
177 self.out.write('[%d]' % ast.value)
178 elif ast.type == 'Cast':
179 # ast.value was added by the typechecker.
180 self.out.write("['%s'," % ast.value)
181 self.compile(ast.children[0])
182 self.out.write(']')
183 elif ast.type == 'TypeCase':
184 self.out.write('if (')
185 self.compile(ast.children[0])
186 # ast.value was added by the typechecker.
187 self.out.write("[0] == '%s')" % ast.value)
188 self.out.write('{ var save=')
189 self.compile(ast.children[0])
190 self.out.write('; ')
191 self.compile(ast.children[0])
192 self.out.write('=')
193 self.compile(ast.children[0])
194 self.out.write('[1]; ')
195 self.compile(ast.children[2])
196 self.compile(ast.children[0])
197 self.out.write(' =save; }')
198 else:
199 raise NotImplementedError(repr(ast))
0 from castile.builtins import BUILTINS
1 from castile.context import ScopedContext
2 from castile.types import *
3
4
5 class TypeChecker(object):
6 def __init__(self):
7 global_context = {}
8 for (name, (value, type)) in BUILTINS.iteritems():
9 global_context[name] = type
10 self.context = ScopedContext(global_context)
11 self.context = ScopedContext({}, self.context)
12
13 self.forwards = {}
14 self.structs = {} # struct name -> StructDefinition
15 self.struct_fields = {} # struct name -> dict of field name -> pos
16 self.assignable = {}
17 self.return_type = None
18 self.verbose = False
19
20 def set(self, name, type):
21 self.context[name] = type
22 if self.verbose:
23 print '%s: %s' % (name, type)
24 return type
25
26 def assert_eq(self, t1, t2):
27 if t1 == t2:
28 return
29 raise SyntaxError("type mismatch: %s != %s" % (t1, t2))
30
31 def is_assignable(self, ast):
32 assert ast.type == 'VarRef'
33 name = ast.value
34 return name in self.assignable
35
36 def collect_structs(self, ast):
37 for child in ast.children:
38 if child.type == 'StructDefn':
39 self.collect_struct(child)
40
41 def collect_struct(self, ast):
42 name = ast.value
43 if name in self.structs:
44 raise SyntaxError('duplicate struct %s' % name)
45 struct_fields = {}
46 self.struct_fields[name] = struct_fields
47 te = []
48 i = 0
49 for child in ast.children:
50 assert child.type == 'FieldDefn'
51 field_name = child.value
52 if field_name in struct_fields:
53 raise SyntaxError('already-defined field %s' % field_name)
54 struct_fields[field_name] = i
55 i += 1
56 te.append(self.type_of(child.children[0]))
57 self.structs[name] = StructDefinition(ast.value, te)
58
59 # context is modified as side-effect of traversal
60 def type_of(self, ast):
61 if ast.type == 'Op':
62 if ast.value in ('and', 'or'):
63 self.assert_eq(self.type_of(ast.children[0]), Boolean())
64 self.assert_eq(self.type_of(ast.children[1]), Boolean())
65 return Boolean()
66 elif ast.value in ('+', '-', '*', '/'):
67 type1 = self.type_of(ast.children[0])
68 type2 = self.type_of(ast.children[1])
69 self.assert_eq(type1, type2)
70 self.assert_eq(type1, Integer())
71 return Integer()
72 elif ast.value in ('==', '!=', '>', '>=', '<', '<='):
73 type1 = self.type_of(ast.children[0])
74 type2 = self.type_of(ast.children[1])
75 self.assert_eq(type1, type2)
76 return Boolean()
77 elif ast.type == 'Not':
78 type1 = self.type_of(ast.children[0])
79 self.assert_eq(type1, Boolean())
80 return Boolean()
81 elif ast.type == 'IntLit':
82 return Integer()
83 elif ast.type == 'StrLit':
84 return String()
85 elif ast.type == 'FunLit':
86 # TODO: should not be able to see anything but globals in here...
87 # unless it's a closure. Oh, joy.
88 self.context = ScopedContext({}, self.context)
89 self.return_type = None
90 arg_types = self.type_of(ast.children[0]) # args
91 return_type = self.type_of(ast.children[1]) # body
92 if self.return_type is not None:
93 self.assert_eq(return_type, self.return_type)
94 self.context = self.context.parent
95 self.return_type = None
96 # modify AST for compiler's benefit
97 ast.children[1].value = 'function body'
98 return Function(arg_types, return_type)
99 elif ast.type == 'Args':
100 types = []
101 for child in ast.children:
102 types.append(self.type_of(child))
103 return types
104 elif ast.type == 'Arg':
105 return self.set(ast.value, self.type_of(ast.children[0]))
106 elif ast.type == 'Type':
107 map = {
108 'integer': Integer(),
109 'boolean': Boolean(),
110 'string': String(),
111 'void': Void(),
112 }
113 return map[ast.value]
114 elif ast.type == 'FunType':
115 return_type = self.type_of(ast.children[0])
116 return Function([self.type_of(c) for c in ast.children[1:]],
117 return_type)
118 elif ast.type == 'UnionType':
119 return Union([self.type_of(c) for c in ast.children])
120 elif ast.type == 'StructType':
121 return Struct(ast.value)
122 elif ast.type == 'VarDecl':
123 name = ast.value
124 if name in self.context:
125 raise SyntaxError('declaration of %s shadows previous' % name)
126 self.assignable[name] = True
127 self.set(name, self.type_of(ast.children[0]))
128 return Void()
129 elif ast.type == 'VarRef':
130 return self.context[ast.value]
131 elif ast.type == 'None':
132 return Void()
133 elif ast.type == 'FunCall':
134 t1 = self.type_of(ast.children[0])
135 assert isinstance(t1, Function), \
136 '%r is not a function' % t1
137 if len(t1.arg_types) != len(ast.children) - 1:
138 raise SyntaxError("argument mismatch")
139 i = 0
140 for child in ast.children[1:]:
141 self.assert_eq(self.type_of(child), t1.arg_types[i])
142 i += 1
143 return t1.return_type
144 elif ast.type == 'Do':
145 t1 = self.type_of(ast.children[0])
146 return Void()
147 elif ast.type == 'Return':
148 t1 = self.type_of(ast.children[0])
149 if self.return_type is None:
150 self.return_type = t1
151 else:
152 self.assert_eq(t1, self.return_type)
153 return Void()
154 elif ast.type == 'If':
155 t1 = self.type_of(ast.children[0])
156 assert t1 == Boolean()
157 t2 = self.type_of(ast.children[1])
158 if len(ast.children) == 3:
159 t3 = self.type_of(ast.children[2])
160 self.assert_eq(t2, t3)
161 return t2
162 else:
163 return Void()
164 elif ast.type == 'While':
165 t1 = self.type_of(ast.children[0])
166 assert t1 == Boolean()
167 t2 = self.type_of(ast.children[1])
168 return Void()
169 elif ast.type == 'Block':
170 self.context = ScopedContext({}, self.context)
171 if len(ast.children) == 0:
172 ast.t = Void()
173 return Void()
174 for child in ast.children[:-1]:
175 self.assert_eq(self.type_of(child), Void())
176 last = self.type_of(ast.children[-1])
177 self.context = self.context.parent
178 # modify the AST for the compiler's benefit
179 ast.t = last
180 return ast.t
181 elif ast.type == 'Assignment':
182 t1 = self.type_of(ast.children[0])
183 if not self.is_assignable(ast.children[0]):
184 raise SyntaxError('cannot assign to non-local')
185 t2 = self.type_of(ast.children[1])
186 self.assert_eq(t1, t2)
187 return Void()
188 elif ast.type == 'Make':
189 t = self.type_of(ast.children[0])
190 if t.name not in self.structs:
191 raise SyntaxError("undefined struct %s" % t.name)
192 struct_defn = self.structs[t.name]
193 if len(struct_defn.content_types) != len(ast.children) - 1:
194 raise SyntaxError("argument mismatch")
195 i = 0
196 for defn in ast.children[1:]:
197 t1 = self.type_of(defn)
198 self.assert_eq(t1, struct_defn.content_types[i])
199 i += 1
200 return t
201 elif ast.type == 'Index':
202 t = self.type_of(ast.children[0])
203 field_name = ast.value
204 struct_fields = self.struct_fields[t.name]
205 if field_name not in struct_fields:
206 raise SyntaxError("undefined field")
207 index = struct_fields[field_name]
208 # we modify the AST for the evaluator's benefit.
209 ast.value = index
210 # we look up the type from the StructDefinition
211 return self.structs[t.name].content_types[index]
212 elif ast.type == 'TypeCase':
213 t1 = self.type_of(ast.children[0])
214 t2 = self.type_of(ast.children[1])
215
216 if not isinstance(t1, Union):
217 raise SyntaxError('bad typecase, %s not a union' % t1)
218 if not t1.contains(t2):
219 raise SyntaxError('bad typecase, %s not in %s' % (t2, t1))
220 # modify the AST for the evaluator's benefit
221 ast.value = str(t2)
222
223 # typecheck t3 with variable in children[0] having type t2
224 assert ast.children[0].type == 'VarRef'
225 self.context = ScopedContext({}, self.context)
226 self.context[ast.children[0].value] = t2
227 t3 = self.type_of(ast.children[2])
228 self.context = self.context.parent
229 return t3
230 elif ast.type == 'Program':
231 for defn in ast.children:
232 t1 = self.type_of(defn)
233 return Void()
234 elif ast.type == 'Defn':
235 # reset assignable
236 self.assignable = {}
237 t = self.type_of(ast.children[0])
238 if ast.value in self.forwards:
239 self.assert_eq(self.forwards[ast.value], t)
240 del self.forwards[ast.value]
241 else:
242 self.set(ast.value, t)
243 if ast.value == 'main':
244 # any return type is fine, for now, so,
245 # we compare it against itself
246 rt = t.return_type
247 self.assert_eq(t, Function([], rt))
248 return t
249 elif ast.type == 'Forward':
250 t = self.type_of(ast.children[0])
251 self.forwards[ast.value] = t
252 return self.set(ast.value, t)
253 elif ast.type == 'StructDefn':
254 pass
255 elif ast.type == 'Cast':
256 t1 = self.type_of(ast.children[0])
257 t2 = self.type_of(ast.children[1])
258 if not isinstance(t2, Union):
259 raise SyntaxError('bad cast, not a union: %s' % t2)
260 if not t2.contains(t1):
261 raise SyntaxError('bad cast, %s does not include %s' %
262 (t2, t1))
263 # we modify the ast here for the evaluator's benefit.
264 ast.value = str(t1)
265 return t2
266 else:
267 raise NotImplementedError(repr(ast))
+0
-200
src/castile/compiler.py less more
0 from castile.types import Void
1
2 OPS = {
3 'and': '&&',
4 'or': '||',
5 '==': '===',
6 }
7
8
9 class Compiler(object):
10 def __init__(self, out):
11 self.out = out
12
13 def commas(self, asts, sep=','):
14 if asts:
15 for child in asts[:-1]:
16 self.compile(child)
17 self.out.write(sep)
18 self.compile(asts[-1])
19
20 def compile(self, ast):
21 if ast.type == 'Program':
22 self.out.write("""\
23 /* AUTOMATICALLY GENERATED EDIT AT OWN RISK */
24
25 var print = function(s) { console.log(s); }
26 var len = function(s) { return s.length; }
27 var concat = function(s1,s2) { return s1 + s2; }
28 var substr = function(s,p,k) { return s.substr(p, k); }
29
30 var repr = function(o) {
31 if (typeof o === "string") {
32 return "'" + o + "'";
33 } else if (o === true) {
34 return "True";
35 } else if (o === false) {
36 return "False";
37 } else if (o === undefined) {
38 return "";
39 } else if (typeof o === "object") {
40 var s = "(";
41 for (var i = 0; i < o.length; i++) {
42 s += repr(o[i]);
43 if (i != o.length - 1) { s += ', '; }
44 }
45 s += ")";
46 return s;
47 } else {
48 return o;
49 }
50 }
51
52 """)
53 for child in ast.children:
54 self.compile(child)
55 self.out.write("""\
56
57 var result = main();
58 print(repr(result));
59 """)
60 elif ast.type == 'Defn':
61 self.out.write('%s = ' % ast.value)
62 self.compile(ast.children[0])
63 self.out.write(';\n')
64 elif ast.type in ('StructDefn', 'Forward'):
65 pass
66 elif ast.type == 'FunLit':
67 self.out.write('function(')
68 self.compile(ast.children[0])
69 self.out.write(')\n')
70 self.compile(ast.children[1])
71 elif ast.type == 'Args':
72 self.commas(ast.children)
73 elif ast.type == 'Arg':
74 self.out.write(ast.value)
75 elif ast.type == 'Block':
76 # typechecker assigned ast.t the type of this block
77 # typechecker assigned value 'function body' if it is a fn bd
78 self.out.write('{')
79 if not ast.children:
80 if ast.value == 'function body':
81 self.out.write('return undefined;')
82 elif ast.t == Void():
83 for child in ast.children:
84 self.compile(child)
85 self.out.write(';\n')
86 if ast.value == 'function body':
87 self.out.write('return undefined;')
88 elif ast.children[-1].type == 'If':
89 for child in ast.children:
90 self.compile(child)
91 self.out.write(';\n')
92 if ast.value == 'function body':
93 self.out.write('return result;')
94 else:
95 for child in ast.children[:-1]:
96 self.compile(child)
97 self.out.write(';\n')
98 if ast.value == 'function body':
99 self.out.write('return ')
100 self.compile(ast.children[-1])
101 self.out.write(';\n')
102 else:
103 self.out.write('result = ')
104 self.compile(ast.children[-1])
105 self.out.write(';\n')
106 self.out.write('}')
107 elif ast.type == 'VarDecl':
108 self.out.write('var %s = ' % ast.value)
109 self.compile(ast.children[0])
110 elif ast.type == 'While':
111 self.out.write('while (')
112 self.compile(ast.children[0])
113 self.out.write(')')
114 self.compile(ast.children[1])
115 elif ast.type == 'Op':
116 self.out.write('(')
117 self.compile(ast.children[0])
118 self.out.write(' %s ' % OPS.get(ast.value, ast.value))
119 self.compile(ast.children[1])
120 self.out.write(')')
121 elif ast.type == 'VarRef':
122 self.out.write(ast.value)
123 elif ast.type == 'FunCall':
124 self.compile(ast.children[0])
125 self.out.write('(')
126 self.commas(ast.children[1:])
127 self.out.write(')')
128 elif ast.type == 'If':
129 if ast.children[1].t == Void():
130 self.out.write('if(')
131 self.compile(ast.children[0])
132 self.out.write(')')
133 if len(ast.children) == 3: # if-else
134 self.compile(ast.children[1])
135 self.out.write(' else ')
136 self.compile(ast.children[2])
137 else: # just-if
138 self.compile(ast.children[1])
139 else:
140 # this assumes you return the result from the current
141 # function, but this assumption is safe, because if you
142 # didn't, it wouldn't typecheck.
143 self.out.write('{ var result; if(')
144 self.compile(ast.children[0])
145 self.out.write(')')
146 self.compile(ast.children[1])
147 self.out.write(' else ')
148 self.compile(ast.children[2])
149 self.out.write('return result; }')
150 elif ast.type == 'Return':
151 self.out.write('return ')
152 self.compile(ast.children[0])
153 elif ast.type == 'Do':
154 self.compile(ast.children[0])
155 elif ast.type == 'Not':
156 self.out.write('!(')
157 self.compile(ast.children[0])
158 self.out.write(')')
159 elif ast.type == 'None':
160 self.out.write('null')
161 elif ast.type == 'IntLit':
162 self.out.write(str(ast.value))
163 elif ast.type == 'StrLit':
164 self.out.write("'%s'" % ast.value)
165 elif ast.type == 'Assignment':
166 self.compile(ast.children[0])
167 self.out.write(' = ')
168 self.compile(ast.children[1])
169 elif ast.type == 'Make':
170 self.out.write('[')
171 self.commas(ast.children[1:])
172 self.out.write(']')
173 elif ast.type == 'Index':
174 self.compile(ast.children[0])
175 # ast.value was converted from a field name to an index by
176 # the typechecker.
177 self.out.write('[%d]' % ast.value)
178 elif ast.type == 'Cast':
179 # ast.value was added by the typechecker.
180 self.out.write("['%s'," % ast.value)
181 self.compile(ast.children[0])
182 self.out.write(']')
183 elif ast.type == 'TypeCase':
184 self.out.write('if (')
185 self.compile(ast.children[0])
186 # ast.value was added by the typechecker.
187 self.out.write("[0] == '%s')" % ast.value)
188 self.out.write('{ var save=')
189 self.compile(ast.children[0])
190 self.out.write('; ')
191 self.compile(ast.children[0])
192 self.out.write('=')
193 self.compile(ast.children[0])
194 self.out.write('[1]; ')
195 self.compile(ast.children[2])
196 self.compile(ast.children[0])
197 self.out.write(' =save; }')
198 else:
199 raise NotImplementedError(repr(ast))
99
1010 from castile.parser import Parser
1111 from castile.eval import Program
12 from castile.types import TypeChecker
13 from castile.compiler import Compiler
12 from castile.checker import TypeChecker
13 from castile.backends.javascript import Compiler
1414
1515
1616 def main(argv):
0 from castile.context import ScopedContext
1
2
30 class Type(object):
41 # Note: type equality relies on (str), so we can't directly
52 # compare infinite types. But with structs, we shouldn't have to.
6966 h += ', '.join([str(t) for t in self.content_types])
7067 h += ')'
7168 return h
72
73
74 class TypeChecker(object):
75 def __init__(self):
76 from castile.builtins import BUILTINS
77 global_context = {}
78 for (name, (value, type)) in BUILTINS.iteritems():
79 global_context[name] = type
80 self.context = ScopedContext(global_context)
81 self.context = ScopedContext({}, self.context)
82
83 self.forwards = {}
84 self.structs = {} # struct name -> StructDefinition
85 self.struct_fields = {} # struct name -> dict of field name -> pos
86 self.assignable = {}
87 self.return_type = None
88 self.verbose = False
89
90 def set(self, name, type):
91 self.context[name] = type
92 if self.verbose:
93 print '%s: %s' % (name, type)
94 return type
95
96 def assert_eq(self, t1, t2):
97 if t1 == t2:
98 return
99 raise SyntaxError("type mismatch: %s != %s" % (t1, t2))
100
101 def is_assignable(self, ast):
102 assert ast.type == 'VarRef'
103 name = ast.value
104 return name in self.assignable
105
106 def collect_structs(self, ast):
107 for child in ast.children:
108 if child.type == 'StructDefn':
109 self.collect_struct(child)
110
111 def collect_struct(self, ast):
112 name = ast.value
113 if name in self.structs:
114 raise SyntaxError('duplicate struct %s' % name)
115 struct_fields = {}
116 self.struct_fields[name] = struct_fields
117 te = []
118 i = 0
119 for child in ast.children:
120 assert child.type == 'FieldDefn'
121 field_name = child.value
122 if field_name in struct_fields:
123 raise SyntaxError('already-defined field %s' % field_name)
124 struct_fields[field_name] = i
125 i += 1
126 te.append(self.type_of(child.children[0]))
127 self.structs[name] = StructDefinition(ast.value, te)
128
129 # context is modified as side-effect of traversal
130 def type_of(self, ast):
131 if ast.type == 'Op':
132 if ast.value in ('and', 'or'):
133 self.assert_eq(self.type_of(ast.children[0]), Boolean())
134 self.assert_eq(self.type_of(ast.children[1]), Boolean())
135 return Boolean()
136 elif ast.value in ('+', '-', '*', '/'):
137 type1 = self.type_of(ast.children[0])
138 type2 = self.type_of(ast.children[1])
139 self.assert_eq(type1, type2)
140 self.assert_eq(type1, Integer())
141 return Integer()
142 elif ast.value in ('==', '!=', '>', '>=', '<', '<='):
143 type1 = self.type_of(ast.children[0])
144 type2 = self.type_of(ast.children[1])
145 self.assert_eq(type1, type2)
146 return Boolean()
147 elif ast.type == 'Not':
148 type1 = self.type_of(ast.children[0])
149 self.assert_eq(type1, Boolean())
150 return Boolean()
151 elif ast.type == 'IntLit':
152 return Integer()
153 elif ast.type == 'StrLit':
154 return String()
155 elif ast.type == 'FunLit':
156 # TODO: should not be able to see anything but globals in here...
157 # unless it's a closure. Oh, joy.
158 self.context = ScopedContext({}, self.context)
159 self.return_type = None
160 arg_types = self.type_of(ast.children[0]) # args
161 return_type = self.type_of(ast.children[1]) # body
162 if self.return_type is not None:
163 self.assert_eq(return_type, self.return_type)
164 self.context = self.context.parent
165 self.return_type = None
166 # modify AST for compiler's benefit
167 ast.children[1].value = 'function body'
168 return Function(arg_types, return_type)
169 elif ast.type == 'Args':
170 types = []
171 for child in ast.children:
172 types.append(self.type_of(child))
173 return types
174 elif ast.type == 'Arg':
175 return self.set(ast.value, self.type_of(ast.children[0]))
176 elif ast.type == 'Type':
177 map = {
178 'integer': Integer(),
179 'boolean': Boolean(),
180 'string': String(),
181 'void': Void(),
182 }
183 return map[ast.value]
184 elif ast.type == 'FunType':
185 return_type = self.type_of(ast.children[0])
186 return Function([self.type_of(c) for c in ast.children[1:]],
187 return_type)
188 elif ast.type == 'UnionType':
189 return Union([self.type_of(c) for c in ast.children])
190 elif ast.type == 'StructType':
191 return Struct(ast.value)
192 elif ast.type == 'VarDecl':
193 name = ast.value
194 if name in self.context:
195 raise SyntaxError('declaration of %s shadows previous' % name)
196 self.assignable[name] = True
197 self.set(name, self.type_of(ast.children[0]))
198 return Void()
199 elif ast.type == 'VarRef':
200 return self.context[ast.value]
201 elif ast.type == 'None':
202 return Void()
203 elif ast.type == 'FunCall':
204 t1 = self.type_of(ast.children[0])
205 assert isinstance(t1, Function), \
206 '%r is not a function' % t1
207 if len(t1.arg_types) != len(ast.children) - 1:
208 raise SyntaxError("argument mismatch")
209 i = 0
210 for child in ast.children[1:]:
211 self.assert_eq(self.type_of(child), t1.arg_types[i])
212 i += 1
213 return t1.return_type
214 elif ast.type == 'Do':
215 t1 = self.type_of(ast.children[0])
216 return Void()
217 elif ast.type == 'Return':
218 t1 = self.type_of(ast.children[0])
219 if self.return_type is None:
220 self.return_type = t1
221 else:
222 self.assert_eq(t1, self.return_type)
223 return Void()
224 elif ast.type == 'If':
225 t1 = self.type_of(ast.children[0])
226 assert t1 == Boolean()
227 t2 = self.type_of(ast.children[1])
228 if len(ast.children) == 3:
229 t3 = self.type_of(ast.children[2])
230 self.assert_eq(t2, t3)
231 return t2
232 else:
233 return Void()
234 elif ast.type == 'While':
235 t1 = self.type_of(ast.children[0])
236 assert t1 == Boolean()
237 t2 = self.type_of(ast.children[1])
238 return Void()
239 elif ast.type == 'Block':
240 self.context = ScopedContext({}, self.context)
241 if len(ast.children) == 0:
242 ast.t = Void()
243 return Void()
244 for child in ast.children[:-1]:
245 self.assert_eq(self.type_of(child), Void())
246 last = self.type_of(ast.children[-1])
247 self.context = self.context.parent
248 # modify the AST for the compiler's benefit
249 ast.t = last
250 return ast.t
251 elif ast.type == 'Assignment':
252 t1 = self.type_of(ast.children[0])
253 if not self.is_assignable(ast.children[0]):
254 raise SyntaxError('cannot assign to non-local')
255 t2 = self.type_of(ast.children[1])
256 self.assert_eq(t1, t2)
257 return Void()
258 elif ast.type == 'Make':
259 t = self.type_of(ast.children[0])
260 if t.name not in self.structs:
261 raise SyntaxError("undefined struct %s" % t.name)
262 struct_defn = self.structs[t.name]
263 if len(struct_defn.content_types) != len(ast.children) - 1:
264 raise SyntaxError("argument mismatch")
265 i = 0
266 for defn in ast.children[1:]:
267 t1 = self.type_of(defn)
268 self.assert_eq(t1, struct_defn.content_types[i])
269 i += 1
270 return t
271 elif ast.type == 'Index':
272 t = self.type_of(ast.children[0])
273 field_name = ast.value
274 struct_fields = self.struct_fields[t.name]
275 if field_name not in struct_fields:
276 raise SyntaxError("undefined field")
277 index = struct_fields[field_name]
278 # we modify the AST for the evaluator's benefit.
279 ast.value = index
280 # we look up the type from the StructDefinition
281 return self.structs[t.name].content_types[index]
282 elif ast.type == 'TypeCase':
283 t1 = self.type_of(ast.children[0])
284 t2 = self.type_of(ast.children[1])
285
286 if not isinstance(t1, Union):
287 raise SyntaxError('bad typecase, %s not a union' % t1)
288 if not t1.contains(t2):
289 raise SyntaxError('bad typecase, %s not in %s' % (t2, t1))
290 # modify the AST for the evaluator's benefit
291 ast.value = str(t2)
292
293 # typecheck t3 with variable in children[0] having type t2
294 assert ast.children[0].type == 'VarRef'
295 self.context = ScopedContext({}, self.context)
296 self.context[ast.children[0].value] = t2
297 t3 = self.type_of(ast.children[2])
298 self.context = self.context.parent
299 return t3
300 elif ast.type == 'Program':
301 for defn in ast.children:
302 t1 = self.type_of(defn)
303 return Void()
304 elif ast.type == 'Defn':
305 # reset assignable
306 self.assignable = {}
307 t = self.type_of(ast.children[0])
308 if ast.value in self.forwards:
309 self.assert_eq(self.forwards[ast.value], t)
310 del self.forwards[ast.value]
311 else:
312 self.set(ast.value, t)
313 if ast.value == 'main':
314 # any return type is fine, for now, so,
315 # we compare it against itself
316 rt = t.return_type
317 self.assert_eq(t, Function([], rt))
318 return t
319 elif ast.type == 'Forward':
320 t = self.type_of(ast.children[0])
321 self.forwards[ast.value] = t
322 return self.set(ast.value, t)
323 elif ast.type == 'StructDefn':
324 pass
325 elif ast.type == 'Cast':
326 t1 = self.type_of(ast.children[0])
327 t2 = self.type_of(ast.children[1])
328 if not isinstance(t2, Union):
329 raise SyntaxError('bad cast, not a union: %s' % t2)
330 if not t2.contains(t1):
331 raise SyntaxError('bad cast, %s does not include %s' %
332 (t2, t1))
333 # we modify the ast here for the evaluator's benefit.
334 ast.value = str(t1)
335 return t2
336 else:
337 raise NotImplementedError(repr(ast))