view python/ppci/c3/builder.py @ 306:b145f8e6050b

Start on c3 rewrite
author Windel Bouwman
date Mon, 09 Dec 2013 19:00:21 +0100
parents 0615b5308710
children e609d5296ee9
line wrap: on
line source

import logging
from .lexer import Lexer
from .parser import Parser
from .analyse import TypeChecker, Analyzer
from .codegenerator import CodeGenerator
from .analyse import AddScope
from .scope import createTopScope
from .visitor import AstPrinter


class Builder:
    """
        Generates IR-code from c3 source.
        Reports errors to the diagnostics system.
    """
    def __init__(self, diag, target):
        self.logger = logging.getLogger('c3')
        self.diag = diag
        self.lexer = Lexer(diag)
        self.parser = Parser(diag)
        self.tc = TypeChecker(diag)
        self.al = Analyzer(diag)
        self.cg = CodeGenerator()
        self.topScope = createTopScope(target)  # Scope with built in types

    def build(self, srcs, imps=[]):
        """ Create IR-code from sources """
        self.logger.info('Building {} source files'.format(len(srcs)))
        iter(srcs)  # Check if srcs are iterable
        iter(imps)
        self.ok = True
        self.pkgs = {}

        def doParse(src):
            tokens = self.lexer.lex(src)
            return self.parser.parseSource(tokens)
        s_pkgs = set(map(doParse, srcs))
        i_pkgs = set(map(doParse, imps))
        all_pkgs = s_pkgs | i_pkgs
        if not all(all_pkgs):
            self.ok = False
            return

        #for pkg in all_pkgs:
        #    AstPrinter().printAst(pkg)
            
        packages = {pkg.name: pkg for pkg in all_pkgs}
        self.pkgs = packages
        # Fix scopes:
        for pkg in all_pkgs:
            AddScope(self.diag, self.topScope).addScope(pkg)
        if not all(pkg.ok for pkg in all_pkgs):
            self.ok = False
            return

        for pkg in all_pkgs:
            self.al.analyzePackage(pkg, packages)
        if not all(pkg.ok for pkg in all_pkgs):
            self.ok = False
            return

        for pkg in all_pkgs:
            self.tc.checkPackage(pkg)
        if not all(pkg.ok for pkg in all_pkgs):
            self.ok = False
            return

        # Only return ircode when everything is OK
        for pkg in all_pkgs & s_pkgs:
            yield self.cg.gencode(pkg)