Mercurial > lcfOS
diff python/ppci/c3/builder.py @ 308:2e7f55319858
Merged analyse into codegenerator
author | Windel Bouwman |
---|---|
date | Fri, 13 Dec 2013 11:53:29 +0100 |
parents | e609d5296ee9 |
children | 6f4753202b9a |
line wrap: on
line diff
--- a/python/ppci/c3/builder.py Thu Dec 12 20:42:56 2013 +0100 +++ b/python/ppci/c3/builder.py Fri Dec 13 11:53:29 2013 +0100 @@ -2,9 +2,82 @@ from .lexer import Lexer from .parser import Parser from .codegenerator import CodeGenerator -from .analyse import ScopeFiller -from .scope import createTopScope -from .visitor import AstPrinter +from .scope import createTopScope, Scope +from .visitor import AstPrinter, Visitor +from .astnodes import Package, Function, Identifier, Symbol + + +class C3Pass: + def __init__(self, diag): + self.diag = diag + self.logger = logging.getLogger('c3') + self.visitor = Visitor() + + def error(self, msg, loc=None): + self.pkg.ok = False + self.diag.error(msg, loc) + + def visit(self, pkg, pre, post): + self.visitor.visit(pkg, pre, post) + + +class ScopeFiller(C3Pass): + scoped_types = [Package, Function] + + def __init__(self, diag, topScope, packages): + super().__init__(diag) + self.topScope = topScope + self.packages = packages + + """ Scope is attached to the correct modules. """ + def addScope(self, pkg): + self.logger.info('Adding scoping to package {}'.format(pkg.name)) + self.pkg = pkg + # Prepare top level scope and set scope to all objects: + self.scopeStack = [self.topScope] + modScope = Scope(self.CurrentScope) + self.scopeStack.append(modScope) + self.visit(pkg, self.enterScope, self.quitScope) + assert len(self.scopeStack) == 2 + + self.logger.info('Resolving imports for package {}'.format(pkg.name)) + # Handle imports: + for i in pkg.imports: + if i not in self.packages: + self.error('Cannot import {}'.format(i)) + continue + pkg.scope.addSymbol(self.packages[i]) + + @property + def CurrentScope(self): + return self.scopeStack[-1] + + 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): + # Attach scope to references: + if type(sym) is Identifier: + sym.scope = self.CurrentScope + + # Add symbols to current scope: + if isinstance(sym, Symbol): + self.addSymbol(sym) + sym.scope = self.CurrentScope + + # Create subscope for items creating a scope: + if type(sym) in self.scoped_types: + newScope = Scope(self.CurrentScope) + self.scopeStack.append(newScope) + sym.innerScope = self.CurrentScope + + def quitScope(self, sym): + # Pop out of scope: + if type(sym) in self.scoped_types: + self.scopeStack.pop(-1) class Builder: