comparison python/c3/analyse.py @ 287:1c7c1e619be8

File movage
author Windel Bouwman
date Thu, 21 Nov 2013 11:57:27 +0100
parents 6f2423df0675
children a747a45dcd78
comparison
equal deleted inserted replaced
286:d9df72971cbf 287:1c7c1e619be8
1 import logging 1 import logging
2 from .visitor import Visitor 2 from .visitor import Visitor
3 from .astnodes import * 3 from .astnodes import *
4 from .scope import Scope, topScope 4 from .scope import *
5 from .typecheck import theType 5
6 6
7 class Analyzer: 7 class Analyzer:
8 """ 8 """
9 Context handling is done here. 9 Context handling is done here.
10 Scope is attached to the correct modules. 10 Scope is attached to the correct modules.
11 This class checks names and references 11 This class checks names and references.
12 """ 12 """
13 def __init__(self, diag): 13 def __init__(self, diag):
14 self.diag = diag 14 self.diag = diag
15 self.logger = logging.getLogger('c3') 15 self.logger = logging.getLogger('c3')
16 16
17 def analyzePackage(self, pkg, packageProvider): 17 def analyzePackage(self, pkg, packageProvider):
18 self.logger.info('Checking package {}'.format(pkg.name)) 18 self.logger.info('Checking package {}'.format(pkg.name))
19 self.ok = True 19 self.ok = True
20 visitor = Visitor() 20 visitor = Visitor()
21 # Prepare top level scope: 21 # Prepare top level scope and set scope to all objects:
22 self.scopeStack = [topScope] 22 self.scopeStack = [topScope]
23 modScope = Scope(self.CurrentScope) 23 modScope = Scope(self.CurrentScope)
24 self.scopeStack.append(modScope) 24 self.scopeStack.append(modScope)
25 visitor.visit(pkg, self.enterScope, self.quitScope) 25 visitor.visit(pkg, self.enterScope, self.quitScope)
26 del self.scopeStack 26 del self.scopeStack
32 self.error('Cannot import {}'.format(i)) 32 self.error('Cannot import {}'.format(i))
33 continue 33 continue
34 for x in ip.declarations: 34 for x in ip.declarations:
35 modScope.addSymbol(x) 35 modScope.addSymbol(x)
36 visitor.visit(pkg, self.findRefs) 36 visitor.visit(pkg, self.findRefs)
37 visitor.visit(pkg, self.sanity)
38 return self.ok 37 return self.ok
39 38
40 def error(self, msg, loc=None): 39 def error(self, msg, loc=None):
41 self.ok = False 40 self.ok = False
42 self.diag.error(msg, loc) 41 self.diag.error(msg, loc)
80 if hasattr(s, 'addRef'): 79 if hasattr(s, 'addRef'):
81 # TODO: make this nicer 80 # TODO: make this nicer
82 s.addRef(None) 81 s.addRef(None)
83 return s 82 return s
84 else: 83 else:
85 self.ok = False 84 self.error('Cannot resolve name {0}'.format(d.tname), d.loc)
86 msg = 'Cannot resolve name {0}'.format(d.tname)
87 self.diag.error(msg, d.loc)
88 85
89 def resolveType(self, t, scope): 86 def resolveType(self, t, scope):
90 # TODO: what about structs?
91 if type(t) is PointerType: 87 if type(t) is PointerType:
92 t.ptype = self.resolveType(t.ptype, scope) 88 t.ptype = self.resolveType(t.ptype, scope)
93 return t 89 return t
94 elif type(t) is StructureType: 90 elif type(t) is StructureType:
95 offset = 0 91 offset = 0
129 if isinstance(d, Variable): 125 if isinstance(d, Variable):
130 d.isLocal = True 126 d.isLocal = True
131 elif type(sym) is DefinedType: 127 elif type(sym) is DefinedType:
132 sym.typ = self.resolveType(sym.typ, sym.scope) 128 sym.typ = self.resolveType(sym.typ, sym.scope)
133 129
134 def sanity(self, sym): 130 # Type checking:
135 if type(sym) is FunctionType: 131
132 def theType(t):
133 """
134 Recurse until a 'real' type is found
135 """
136 if type(t) is DefinedType:
137 return theType(t.typ)
138 return t
139
140 def equalTypes(a, b):
141 """
142 Compare types a and b for equality.
143 Not equal until proven otherwise.
144 """
145 # Recurse into named types:
146 a = theType(a)
147 b = theType(b)
148
149 # Compare for structural equivalence:
150 if type(a) is type(b):
151 if type(a) is BaseType:
152 return a.name == b.name
153 elif type(a) is PointerType:
154 return equalTypes(a.ptype, b.ptype)
155 elif type(a) is StructureType:
156 if len(a.mems) != len(b.mems):
157 return False
158 for amem, bmem in zip(a.mems, b.mems):
159 if not equalTypes(amem.typ, bmem.typ):
160 return False
161 return True
162 else:
163 raise Exception('Type compare for {} not implemented'.format(type(a)))
164 return False
165
166 def canCast(fromT, toT):
167 fromT = theType(fromT)
168 toT = theType(toT)
169 if isinstance(fromT, PointerType) and isinstance(toT, PointerType):
170 return True
171 elif fromT is intType and isinstance(toT, PointerType):
172 return True
173 return False
174
175 def expectRval(s):
176 # TODO: solve this better
177 s.expect_rvalue = True
178
179 class TypeChecker:
180 def __init__(self, diag):
181 self.diag = diag
182
183 def error(self, msg, loc):
184 """
185 Wrapper that registers the message and marks the result invalid
186 """
187 self.diag.error(msg, loc)
188 self.ok = False
189
190 def checkPackage(self, pkg):
191 self.ok = True
192 visitor = Visitor()
193 visitor.visit(pkg, f_post=self.check2)
194 return self.ok
195
196 def check2(self, sym):
197 if type(sym) in [IfStatement, WhileStatement]:
198 if not equalTypes(sym.condition.typ, boolType):
199 msg = 'Condition must be of type {}'.format(boolType)
200 self.error(msg, sym.condition.loc)
201 elif type(sym) is Assignment:
202 l, r = sym.lval, sym.rval
203 if not equalTypes(l.typ, r.typ):
204 msg = 'Cannot assign {} to {}'.format(r.typ, l.typ)
205 self.error(msg, sym.loc)
206 if not l.lvalue:
207 self.error('No valid lvalue {}'.format(l), l.loc)
208 #if sym.rval.lvalue:
209 # self.error('Right hand side must be an rvalue', sym.rval.loc)
210 expectRval(sym.rval)
211 elif type(sym) is ReturnStatement:
136 pass 212 pass
137 elif type(sym) is Function: 213 elif type(sym) is FunctionCall:
214 # Check arguments:
215 ngiv = len(sym.args)
216 ptypes = sym.proc.typ.parametertypes
217 nreq = len(ptypes)
218 if ngiv != nreq:
219 self.error('Function {2}: {0} arguments required, {1} given'.format(nreq, ngiv, sym.proc.name), sym.loc)
220 else:
221 for a, at in zip(sym.args, ptypes):
222 expectRval(a)
223 if not equalTypes(a.typ, at):
224 self.error('Got {0}, expected {1}'.format(a.typ, at), a.loc)
225 # determine return type:
226 sym.typ = sym.proc.typ.returntype
227 elif type(sym) is VariableUse:
228 sym.lvalue = True
229 if isinstance(sym.target, Variable):
230 sym.typ = sym.target.typ
231 else:
232 print('warning {} has no target, defaulting to int'.format(sym))
233 sym.typ = intType
234 elif type(sym) is Literal:
235 sym.lvalue = False
236 if type(sym.val) is int:
237 sym.typ = intType
238 elif type(sym.val) is float:
239 sym.typ = doubleType
240 elif type(sym.val) is bool:
241 sym.typ = boolType
242 else:
243 raise Exception('Unknown literal type'.format(sym.val))
244 elif type(sym) is Unop:
245 if sym.op == '&':
246 sym.typ = PointerType(sym.a.typ)
247 sym.lvalue = False
248 else:
249 raise Exception('Unknown unop {0}'.format(sym.op))
250 elif type(sym) is Deref:
251 # pointer deref
252 sym.lvalue = True
253 # check if the to be dereferenced variable is a pointer type:
254 ptype = theType(sym.ptr.typ)
255 if type(ptype) is PointerType:
256 sym.typ = ptype.ptype
257 else:
258 self.error('Cannot dereference non-pointer type {}'.format(ptype), sym.loc)
259 sym.typ = intType
260 elif type(sym) is FieldRef:
261 basetype = sym.base.typ
262 sym.lvalue = sym.base.lvalue
263 basetype = theType(basetype)
264 if type(basetype) is StructureType:
265 if basetype.hasField(sym.field):
266 sym.typ = basetype.fieldType(sym.field)
267 else:
268 self.error('{} does not contain field {}'.format(basetype, sym.field), sym.loc)
269 sym.typ = intType
270 else:
271 self.error('Cannot select field {} of non-structure type {}'.format(sym.field, basetype), sym.loc)
272 sym.typ = intType
273 elif type(sym) is Binop:
274 sym.lvalue = False
275 if sym.op in ['+', '-', '*', '/', '<<', '>>', '|', '&']:
276 expectRval(sym.a)
277 expectRval(sym.b)
278 if equalTypes(sym.a.typ, sym.b.typ):
279 if equalTypes(sym.a.typ, intType):
280 sym.typ = sym.a.typ
281 else:
282 self.error('Can only add integers', sym.loc)
283 sym.typ = intType
284 else:
285 # assume void here? TODO: throw exception!
286 sym.typ = intType
287 self.error('Types unequal {} != {}'.format(sym.a.typ, sym.b.typ), sym.loc)
288 elif sym.op in ['>', '<', '==', '<=', '>=']:
289 expectRval(sym.a)
290 expectRval(sym.b)
291 sym.typ = boolType
292 if not equalTypes(sym.a.typ, sym.b.typ):
293 self.error('Types unequal {} != {}'.format(sym.a.typ, sym.b.typ), sym.loc)
294 elif sym.op in ['or', 'and']:
295 sym.typ = boolType
296 if not equalTypes(sym.a.typ, boolType):
297 self.error('Must be {0}'.format(boolType), sym.a.loc)
298 if not equalTypes(sym.b.typ, boolType):
299 self.error('Must be {0}'.format(boolType), sym.b.loc)
300 else:
301 raise Exception('Unknown binop {0}'.format(sym.op))
302 elif isinstance(sym, Variable):
303 # check initial value type:
304 # TODO
138 pass 305 pass
139 306 elif type(sym) is TypeCast:
307 if canCast(sym.a.typ, sym.to_type):
308 sym.typ = sym.to_type
309 else:
310 self.error('Cannot cast {} to {}'.format(sym.a.typ, sym.to_type), sym.loc)
311 sym.typ = intType
312 elif type(sym) is Constant:
313 if not equalTypes(sym.typ, sym.value.typ):
314 self.error('Cannot assign {0} to {1}'.format(sym.value.typ, sym.typ), sym.loc)
315 elif type(sym) in [CompoundStatement, Package, Function, FunctionType, ExpressionStatement, DefinedType]:
316 pass
317 else:
318 raise NotImplementedError('Unknown type check {0}'.format(sym))