Mercurial > lcfOS
view python/c3/analyse.py @ 249:e41e4109addd
Added current position arrow
author | Windel Bouwman |
---|---|
date | Fri, 26 Jul 2013 20:26:05 +0200 |
parents | 521567d17388 |
children | 6ed3d3a82a63 |
line wrap: on
line source
from .visitor import Visitor from .astnodes import * from .scope import Scope, topScope from .typecheck import theType class Analyzer: """ Context handling is done here. Scope is attached to the correct modules. This class checks names and references """ def __init__(self, diag): self.diag = diag def analyzePackage(self, pkg): self.ok = True visitor = Visitor() # Prepare top level scope: self.scopeStack = [topScope] visitor.visit(pkg, self.enterScope, self.quitScope) del self.scopeStack visitor.visit(pkg, self.findRefs) visitor.visit(pkg, self.sanity) return self.ok def error(self, msg, loc=None): self.ok = False self.diag.error(msg, loc) @property def currentScope(self): return self.scopeStack[-1] # Scope creation: def addSymbol(self, sym): if self.currentScope.hasSymbol(sym.name): self.error('Redefinition of {0}'.format(sym.name), sym.loc) else: self.currentScope.addSymbol(sym) def enterScope(self, sym): # Distribute the scope: sym.scope = self.currentScope # Add symbols to current scope: if isinstance(sym, Symbol): self.addSymbol(sym) if isinstance(sym, DefinedType): self.addSymbol(sym) # Create subscope: if type(sym) in [Package, Function]: newScope = Scope(self.currentScope) self.scopeStack.append(newScope) sym.innerScope = self.currentScope def quitScope(self, sym): # Pop out of scope: if type(sym) in [Package, Function]: self.scopeStack.pop(-1) # Reference fixups: def resolveDesignator(self, d, scope): assert type(d) is Designator, type(d) assert type(scope) is Scope if scope.hasSymbol(d.tname): s = scope.getSymbol(d.tname) if hasattr(s, 'addRef'): # TODO: make this nicer s.addRef(None) return s else: self.ok = False msg = 'Cannot resolve name {0}'.format(d.tname) self.diag.error(msg, d.loc) def resolveType(self, t, scope): # TODO: what about structs? if type(t) is PointerType: t.ptype = self.resolveType(t.ptype, scope) return t elif type(t) is StructureType: offset = 0 for mem in t.mems: mem.offset = offset mem.typ = self.resolveType(mem.typ, scope) offset += theType(mem.typ).bytesize t.bytesize = offset return t elif type(t) is Designator: t = self.resolveDesignator(t, scope) if t: return self.resolveType(t, scope) elif isinstance(t, Type): # Already resolved?? return t else: raise Exception('Error resolving type {} {}'.format(t, type(t))) def findRefs(self, sym): if type(sym) in [Variable, Constant]: sym.typ = self.resolveType(sym.typ, sym.scope) elif type(sym) is TypeCast: sym.to_type = self.resolveType(sym.to_type, sym.scope) elif type(sym) is VariableUse: sym.target = self.resolveDesignator(sym.target, sym.scope) elif type(sym) is FunctionCall: varuse = sym.proc sym.proc = self.resolveDesignator(varuse.target, sym.scope) elif type(sym) is Function: # Checkup function type: ft = sym.typ ft.returntype = self.resolveType(ft.returntype, sym.scope) ft.parametertypes = [self.resolveType(pt, sym.scope) for pt in ft.parametertypes] elif type(sym) is DefinedType: sym.typ = self.resolveType(sym.typ, sym.scope) def sanity(self, sym): if type(sym) is FunctionType: pass elif type(sym) is Function: pass