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: