view python/ppci/c3/builder.py @ 307:e609d5296ee9

Massive rewrite of codegenerator
author Windel Bouwman
date Thu, 12 Dec 2013 20:42:56 +0100
parents b145f8e6050b
children 2e7f55319858
line wrap: on
line source

import logging
from .lexer import Lexer
from .parser import Parser
from .codegenerator import CodeGenerator
from .analyse import ScopeFiller
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.cg = CodeGenerator(diag)
        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 = {}

        # Parsing stage (phase 1)
        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

        # Fix scopes and package refs (phase 1.5)
        packages = {pkg.name: pkg for pkg in all_pkgs}
        self.pkgs = packages

        scopeFiller = ScopeFiller(self.diag, self.topScope, packages)
        # Fix scopes:
        for pkg in all_pkgs:
            scopeFiller.addScope(pkg)
        if not all(pkg.ok for pkg in all_pkgs):
            self.ok = False
            return

        # Generate intermediate code (phase 2)
        # Only return ircode when everything is OK
        for pkg in all_pkgs & s_pkgs:
            yield self.cg.gencode(pkg)
        if not all(pkg.ok for pkg in all_pkgs):
            self.ok = False
            return