Mercurial > lcfOS
diff python/c3/analyse.py @ 215:c1ccb1cb4cef
Major changes in c3 frontend
author | Windel Bouwman |
---|---|
date | Fri, 05 Jul 2013 13:00:03 +0200 |
parents | 46d62dadd61b |
children | 8b2e5f3cd579 |
line wrap: on
line diff
--- a/python/c3/analyse.py Fri Jul 05 11:18:58 2013 +0200 +++ b/python/c3/analyse.py Fri Jul 05 13:00:03 2013 +0200 @@ -1,40 +1,86 @@ from .visitor import Visitor from .astnodes import * +from .scope import Scope, topScope class Analyzer: - """ This class checks names and references """ - def __init__(self, diag): - self.diag = diag - self.visitor = Visitor(self.a1, self.analyze) + """ + 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): + def analyzePackage(self, pkg): self.ok = True - self.visitor.visit(pkg) + visitor = Visitor() + # Prepare top level scope: + self.curScope = topScope + visitor.visit(pkg, self.enterScope, self.quitScope) + del self.curScope + visitor.visit(pkg, self.findRefs) + visitor.visit(pkg, self.sanity) return self.ok - def resolveDesignator(self, d, referee=None): - assert type(d) is Designator - if d.scope.hasSymbol(d.tname): - s = d.scope.getSymbol(d.tname) - if hasattr(s, 'addRef'): - # TODO: make this nicer - s.addRef(referee) - return s - else: - self.ok = False - msg = 'Cannot resolve name {0}'.format(d.tname) - self.diag.error(msg, d.loc) - def a1(self, sym): - pass - def analyze(self, sym): - if type(sym) in [Variable, Constant]: - sym.typ = self.resolveDesignator(sym.typ, sym) - elif type(sym) is Function: - pass - elif type(sym) is VariableUse: - sym.target = self.resolveDesignator(sym.target, sym) - elif type(sym) is FunctionCall: - sym.proc = self.resolveDesignator(sym.proc, sym) - elif type(sym) is FunctionType: - sym.returntype = self.resolveDesignator(sym.returntype) - sym.parametertypes = [self.resolveDesignator(pt) for pt in sym.parametertypes] + + def error(self, msg, loc=None): + self.ok = False + self.diag.error(msg, loc) + + # Scope creation: + def addSymbol(self, sym): + if self.curScope.hasSymbol(sym.name): + self.error('Redefinition of {0}'.format(sym.name), sym.loc) + else: + self.curScope.addSymbol(sym) + + def enterScope(self, sym): + # Distribute the scope: + sym.scope = self.curScope + + # Add symbols to current scope: + if isinstance(sym, Symbol): + self.addSymbol(sym) + + # Create subscope: + if type(sym) in [Package, Function]: + self.curScope = Scope(self.curScope) + + def quitScope(self, sym): + # Pop out of scope: + if type(sym) in [Package, Function]: + self.curScope = self.curScope.parent + # Reference fixups: + def resolveDesignator(self, d, scope): + assert type(d) is Designator + 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 findRefs(self, sym): + if type(sym) in [Variable, Constant]: + sym.typ = self.resolveDesignator(sym.typ, sym.scope) + elif type(sym) is VariableUse: + sym.target = self.resolveDesignator(sym.target, sym.scope) + elif type(sym) is FunctionCall: + sym.proc = self.resolveDesignator(sym.proc, sym.scope) + elif type(sym) is Function: + # Checkup function type: + ft = sym.typ + ft.returntype = self.resolveDesignator(ft.returntype, sym.scope) + ft.parametertypes = [self.resolveDesignator(pt, sym.scope) for pt in ft.parametertypes] + + def sanity(self, sym): + if type(sym) is FunctionType: + pass + elif type(sym) is Function: + pass +