5 | 5 |
|
6 | 6 |
|
7 | 7 |
class CastileTypeError(ValueError):
|
8 | |
pass
|
|
8 |
def __init__(self, ast, message, *args, **kwargs):
|
|
9 |
message = 'line {}: {}'.format(ast.line, message)
|
|
10 |
super(CastileTypeError, self).__init__(message, *args, **kwargs)
|
9 | 11 |
|
10 | 12 |
|
11 | 13 |
class StructDefinition(object):
|
|
48 | 50 |
print('%s: %s' % (name, type))
|
49 | 51 |
return type
|
50 | 52 |
|
51 | |
def assert_eq(self, t1, t2):
|
|
53 |
def assert_eq(self, ast, t1, t2):
|
52 | 54 |
if t1 == t2:
|
53 | 55 |
return
|
54 | |
raise CastileTypeError("type mismatch: %s != %s" % (t1, t2))
|
|
56 |
raise CastileTypeError(ast, "type mismatch: %s != %s" % (t1, t2))
|
55 | 57 |
|
56 | 58 |
def collect_structs(self, ast):
|
57 | 59 |
for child in ast.children:
|
|
61 | 63 |
def collect_struct(self, ast):
|
62 | 64 |
name = ast.value
|
63 | 65 |
if name in self.structs:
|
64 | |
raise CastileTypeError('duplicate struct %s' % name)
|
|
66 |
raise CastileTypeError(ast, 'duplicate struct %s' % name)
|
65 | 67 |
struct_fields = {}
|
66 | 68 |
type_exprs = []
|
67 | 69 |
i = 0
|
|
73 | 75 |
assert child.tag == 'FieldDefn', child.tag
|
74 | 76 |
field_name = child.value
|
75 | 77 |
if field_name in struct_fields:
|
76 | |
raise CastileTypeError('already-defined field %s' % field_name)
|
|
78 |
raise CastileTypeError(child, 'already-defined field %s' % field_name)
|
77 | 79 |
struct_fields[field_name] = i
|
78 | 80 |
i += 1
|
79 | 81 |
type_exprs.append(self.type_of(child.children[0]))
|
|
82 | 84 |
def resolve_structs(self, ast):
|
83 | 85 |
if isinstance(ast.type, Struct):
|
84 | 86 |
if ast.type.name not in self.structs:
|
85 | |
raise CastileTypeError('undefined struct %s' % ast.type.name)
|
|
87 |
raise CastileTypeError(ast, 'undefined struct %s' % ast.type.name)
|
86 | 88 |
ast.type.defn = self.structs[ast.type.name]
|
87 | 89 |
for child in ast.children:
|
88 | 90 |
self.resolve_structs(child)
|
|
91 | 93 |
def type_of(self, ast):
|
92 | 94 |
if ast.tag == 'Op':
|
93 | 95 |
if ast.value in ('and', 'or'):
|
94 | |
self.assert_eq(self.type_of(ast.children[0]), Boolean())
|
95 | |
self.assert_eq(self.type_of(ast.children[1]), Boolean())
|
|
96 |
self.assert_eq(ast, self.type_of(ast.children[0]), Boolean())
|
|
97 |
self.assert_eq(ast, self.type_of(ast.children[1]), Boolean())
|
96 | 98 |
ast.type = Boolean()
|
97 | 99 |
elif ast.value in ('+', '-', '*', '/'):
|
98 | 100 |
type1 = self.type_of(ast.children[0])
|
99 | 101 |
type2 = self.type_of(ast.children[1])
|
100 | |
self.assert_eq(type1, type2)
|
101 | |
self.assert_eq(type1, Integer())
|
|
102 |
self.assert_eq(ast, type1, type2)
|
|
103 |
self.assert_eq(ast, type1, Integer())
|
102 | 104 |
ast.type = Integer()
|
103 | 105 |
elif ast.value in ('==', '!=', '>', '>=', '<', '<='):
|
104 | 106 |
type1 = self.type_of(ast.children[0])
|
105 | 107 |
type2 = self.type_of(ast.children[1])
|
106 | |
self.assert_eq(type1, type2)
|
|
108 |
self.assert_eq(ast, type1, type2)
|
107 | 109 |
if isinstance(type1, Struct):
|
108 | |
raise CastileTypeError("structs cannot be compared")
|
|
110 |
raise CastileTypeError(ast, "structs cannot be compared")
|
109 | 111 |
if isinstance(type1, Union) and type1.contains_instance_of(Struct):
|
110 | |
raise CastileTypeError("unions containing structs cannot be compared")
|
|
112 |
raise CastileTypeError(ast, "unions containing structs cannot be compared")
|
111 | 113 |
ast.type = Boolean()
|
112 | 114 |
elif ast.tag == 'Not':
|
113 | 115 |
type1 = self.type_of(ast.children[0])
|
114 | |
self.assert_eq(type1, Boolean())
|
|
116 |
self.assert_eq(ast, type1, Boolean())
|
115 | 117 |
ast.type = Boolean()
|
116 | 118 |
elif ast.tag == 'IntLit':
|
117 | 119 |
ast.type = Integer()
|
|
121 | 123 |
ast.type = Boolean()
|
122 | 124 |
elif ast.tag == 'FunLit':
|
123 | 125 |
save_context = self.context
|
124 | |
self.context = ScopedContext({}, self.toplevel_context,
|
125 | |
level='argument')
|
|
126 |
self.context = ScopedContext(
|
|
127 |
{}, self.toplevel_context, level='argument'
|
|
128 |
)
|
126 | 129 |
self.return_type = None
|
127 | 130 |
arg_types = self.type_of(ast.children[0]) # args
|
128 | 131 |
t = self.type_of(ast.children[1]) # body
|
129 | |
self.assert_eq(t, Void())
|
|
132 |
self.assert_eq(ast, t, Void())
|
130 | 133 |
self.context = save_context
|
131 | 134 |
return_type = self.return_type
|
132 | 135 |
self.return_type = None
|
|
151 | 154 |
elif ast.tag == 'Body':
|
152 | 155 |
self.context = ScopedContext({}, self.context,
|
153 | 156 |
level='local')
|
154 | |
self.assert_eq(self.type_of(ast.children[1]), Void())
|
|
157 |
self.assert_eq(ast, self.type_of(ast.children[1]), Void())
|
155 | 158 |
self.context = self.context.parent
|
156 | 159 |
ast.type = Void()
|
157 | 160 |
elif ast.tag == 'FunType':
|
|
164 | 167 |
for c in ast.children:
|
165 | 168 |
type_ = self.type_of(c)
|
166 | 169 |
if type_ in types:
|
167 | |
raise CastileTypeError("bad union type")
|
|
170 |
raise CastileTypeError(c, "bad union type")
|
168 | 171 |
types.append(type_)
|
169 | 172 |
ast.type = Union(types)
|
170 | 173 |
elif ast.tag == 'StructType':
|
|
179 | 182 |
assert isinstance(t1, Function), \
|
180 | 183 |
'%r is not a function' % t1
|
181 | 184 |
if len(t1.arg_types) != len(ast.children) - 1:
|
182 | |
raise CastileTypeError("argument mismatch")
|
|
185 |
raise CastileTypeError(ast, "argument mismatch")
|
183 | 186 |
i = 0
|
184 | 187 |
for child in ast.children[1:]:
|
185 | |
self.assert_eq(self.type_of(child), t1.arg_types[i])
|
|
188 |
self.assert_eq(ast, self.type_of(child), t1.arg_types[i])
|
186 | 189 |
i += 1
|
187 | 190 |
ast.type = t1.return_type
|
188 | 191 |
elif ast.tag == 'Return':
|
|
190 | 193 |
if self.return_type is None:
|
191 | 194 |
self.return_type = t1
|
192 | 195 |
else:
|
193 | |
self.assert_eq(t1, self.return_type)
|
|
196 |
self.assert_eq(ast, t1, self.return_type)
|
194 | 197 |
ast.type = Void()
|
195 | 198 |
elif ast.tag == 'Break':
|
196 | 199 |
ast.type = Void()
|
|
203 | 206 |
if len(ast.children) == 3:
|
204 | 207 |
# TODO useless! is void.
|
205 | 208 |
t3 = self.type_of(ast.children[2])
|
206 | |
self.assert_eq(t2, t3)
|
|
209 |
self.assert_eq(ast, t2, t3)
|
207 | 210 |
ast.type = t2
|
208 | 211 |
else:
|
209 | 212 |
ast.type = Void()
|
|
212 | 215 |
within_control = self.within_control
|
213 | 216 |
self.within_control = True
|
214 | 217 |
t1 = self.type_of(ast.children[0])
|
215 | |
self.assert_eq(t1, Boolean())
|
|
218 |
self.assert_eq(ast, t1, Boolean())
|
216 | 219 |
t2 = self.type_of(ast.children[1])
|
217 | 220 |
ast.type = Void()
|
218 | 221 |
self.within_control = within_control
|
219 | 222 |
elif ast.tag == 'Block':
|
220 | 223 |
for child in ast.children:
|
221 | |
self.assert_eq(self.type_of(child), Void())
|
|
224 |
self.assert_eq(ast, self.type_of(child), Void())
|
222 | 225 |
ast.type = Void()
|
223 | 226 |
elif ast.tag == 'Assignment':
|
224 | 227 |
t2 = self.type_of(ast.children[1])
|
|
226 | 229 |
name = ast.children[0].value
|
227 | 230 |
if ast.aux == 'defining instance':
|
228 | 231 |
if self.within_control:
|
229 | |
raise CastileTypeError('definition of %s within control block' % name)
|
|
232 |
raise CastileTypeError(ast, 'definition of %s within control block' % name)
|
230 | 233 |
if name in self.context:
|
231 | |
raise CastileTypeError('definition of %s shadows previous' % name)
|
|
234 |
raise CastileTypeError(ast, 'definition of %s shadows previous' % name)
|
232 | 235 |
self.set(name, t2)
|
233 | 236 |
t1 = t2
|
234 | 237 |
else:
|
235 | 238 |
if name not in self.context:
|
236 | |
raise CastileTypeError('variable %s used before definition' % name)
|
|
239 |
raise CastileTypeError(ast, 'variable %s used before definition' % name)
|
237 | 240 |
t1 = self.type_of(ast.children[0])
|
238 | |
self.assert_eq(t1, t2)
|
|
241 |
self.assert_eq(ast, t1, t2)
|
239 | 242 |
# not quite useless now (typecase still likes this)
|
240 | 243 |
if self.context.level(ast.children[0].value) != 'local':
|
241 | |
raise CastileTypeError('cannot assign to non-local')
|
|
244 |
raise CastileTypeError(ast, 'cannot assign to non-local')
|
242 | 245 |
ast.type = Void()
|
243 | 246 |
elif ast.tag == 'Make':
|
244 | 247 |
t = self.type_of(ast.children[0])
|
245 | 248 |
if t.name not in self.structs:
|
246 | |
raise CastileTypeError("undefined struct %s" % t.name)
|
|
249 |
raise CastileTypeError(ast, "undefined struct %s" % t.name)
|
247 | 250 |
struct_defn = self.structs[t.name]
|
248 | 251 |
if struct_defn.scope_idents is not None:
|
249 | 252 |
if self.current_defn not in struct_defn.scope_idents:
|
250 | |
raise CastileTypeError("inaccessible struct %s for make: %s not in %s" %
|
|
253 |
raise CastileTypeError(ast, "inaccessible struct %s for make: %s not in %s" %
|
251 | 254 |
(t.name, self.current_defn, struct_defn.scope_idents)
|
252 | 255 |
)
|
253 | 256 |
if len(struct_defn.content_types) != len(ast.children) - 1:
|
254 | |
raise CastileTypeError("argument mismatch; expected {}, got {} in {}".format(
|
|
257 |
raise CastileTypeError(ast, "argument mismatch; expected {}, got {} in {}".format(
|
255 | 258 |
len(struct_defn.content_types), len(ast.children) - 1, ast
|
256 | 259 |
))
|
257 | 260 |
i = 0
|
|
260 | 263 |
t1 = self.type_of(defn)
|
261 | 264 |
pos = struct_defn.field_names[name]
|
262 | 265 |
defn.aux = pos
|
263 | |
self.assert_eq(t1, struct_defn.content_types[pos])
|
|
266 |
self.assert_eq(ast, t1, struct_defn.content_types[pos])
|
264 | 267 |
i += 1
|
265 | 268 |
ast.type = t
|
266 | 269 |
elif ast.tag == 'FieldInit':
|
|
270 | 273 |
struct_defn = self.structs[t.name]
|
271 | 274 |
if struct_defn.scope_idents is not None:
|
272 | 275 |
if self.current_defn not in struct_defn.scope_idents:
|
273 | |
raise CastileTypeError("inaccessible struct %s for access: %s not in %s" %
|
|
276 |
raise CastileTypeError(ast, "inaccessible struct %s for access: %s not in %s" %
|
274 | 277 |
(t.name, self.current_defn, struct_defn.scope_idents)
|
275 | 278 |
)
|
276 | 279 |
field_name = ast.value
|
277 | 280 |
struct_fields = struct_defn.field_names
|
278 | 281 |
if field_name not in struct_fields:
|
279 | |
raise CastileTypeError("undefined field")
|
|
282 |
raise CastileTypeError(ast, "undefined field")
|
280 | 283 |
index = struct_fields[field_name]
|
281 | 284 |
# we make this value available to compiler backends
|
282 | 285 |
ast.aux = index
|
|
286 | 289 |
t1 = self.type_of(ast.children[0])
|
287 | 290 |
t2 = self.type_of(ast.children[1])
|
288 | 291 |
if not isinstance(t1, Union):
|
289 | |
raise CastileTypeError('bad typecase, %s not a union' % t1)
|
|
292 |
raise CastileTypeError(ast, 'bad typecase, %s not a union' % t1)
|
290 | 293 |
if not t1.contains(t2):
|
291 | |
raise CastileTypeError('bad typecase, %s not in %s' % (t2, t1))
|
|
294 |
raise CastileTypeError(ast, 'bad typecase, %s not in %s' % (t2, t1))
|
292 | 295 |
# typecheck t3 with variable in children[0] having type t2
|
293 | 296 |
assert ast.children[0].tag == 'VarRef'
|
294 | 297 |
within_control = self.within_control
|
|
300 | 303 |
self.within_control = within_control
|
301 | 304 |
elif ast.tag == 'Program':
|
302 | 305 |
for defn in ast.children:
|
303 | |
self.assert_eq(self.type_of(defn), Void())
|
|
306 |
self.assert_eq(ast, self.type_of(defn), Void())
|
304 | 307 |
ast.type = Void()
|
305 | 308 |
self.resolve_structs(ast)
|
306 | 309 |
elif ast.tag == 'Defn':
|
|
308 | 311 |
t = self.type_of(ast.children[0])
|
309 | 312 |
self.current_defn = None
|
310 | 313 |
if ast.value in self.forwards:
|
311 | |
self.assert_eq(self.forwards[ast.value], t)
|
|
314 |
self.assert_eq(ast, self.forwards[ast.value], t)
|
312 | 315 |
del self.forwards[ast.value]
|
313 | 316 |
else:
|
314 | 317 |
self.set(ast.value, t)
|
|
316 | 319 |
# any return type is fine, for now, so,
|
317 | 320 |
# we compare it against itself
|
318 | 321 |
rt = t.return_type
|
319 | |
self.assert_eq(t, Function([], rt))
|
|
322 |
self.assert_eq(ast, t, Function([], rt))
|
320 | 323 |
ast.type = Void()
|
321 | 324 |
elif ast.tag == 'Forward':
|
322 | 325 |
t = self.type_of(ast.children[0])
|
|
329 | 332 |
value_t = self.type_of(ast.children[0])
|
330 | 333 |
union_t = self.type_of(ast.children[1])
|
331 | 334 |
if not isinstance(union_t, Union):
|
332 | |
raise CastileTypeError('bad cast, not a union: %s' % union_t)
|
|
335 |
raise CastileTypeError(ast, 'bad cast, not a union: %s' % union_t)
|
333 | 336 |
if not union_t.contains(value_t):
|
334 | 337 |
raise CastileTypeError(
|
335 | |
'bad cast, %s does not include %s' % (union_t, value_t)
|
|
338 |
ast, 'bad cast, %s does not include %s' % (union_t, value_t)
|
336 | 339 |
)
|
337 | 340 |
ast.type = union_t
|
338 | 341 |
else:
|