view 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 source

from .visitor import Visitor
from .astnodes import *
from .scope import Scope, topScope

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.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 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