示例#1
0
    def compile(self, source, env=None, library=False):
        if env == None:
            env = Environment()

        # parse input
        (definitions, errors) = Parser().parse(source)

        # check for errors
        if len(errors) > 0:
            return ("", errors)

        # type checking
        for definition in definitions:
            TypeChecker().check(errors, env, definition)

        # check for errors
        if len(errors) > 0:
            return ("", errors)

        # code generation
        code = ""
        generator = CodeGenerator()
        for node in definitions:
            symbol = node[0].value()
            code += generator.generateDefinition(env, symbol, template)

        # generate library
        if library:
            code += generator.generateLibrary(template)

        return (code, errors)
示例#2
0
    def testFirstFunctionApplyBug(self):
        (definitions, errors) = Parser().parse("""
            //def bug(x) = get([x], 0)
            def test(x) = [x]
            def test2(x) = test(x)
            def test3(x) = get(test(x), 0)
            """)
        env = Environment()
        type1 = TypeChecker().check(errors, env, definitions[0])
        type2 = TypeChecker().check(errors, env, definitions[1])
        type3 = TypeChecker().check(errors, env, definitions[2])

        self.assertEqual(errors, [])
        self.assertEqual(str(type1), "a -> [a]")
        self.assertEqual(str(type2), "a -> [a]")
        self.assertEqual(str(type3), "a -> a")
示例#3
0
def run_pipeline(text):
    ret_text = '\n' + '=================== TEXT ======================'
    ret_text += '\n' + text
    ret_text += '\n' + '================== TOKENS ====================='
    tokens = tokenize_text(text)
    ret_text += '\n' + pprint_tokens(tokens)
    ret_text += '\n' + '=================== PARSE ====================='
    ret_text += '\n'
    parser = Serializer.load(os.getcwd() + '/parser')
    #parser = LR1Parser(G)
    ret_parser = parser([t.token_type for t in tokens])
    parse, operations = ret_parser
    if parse is None:
        return ret_text + "\nParsing Error at " + operations
    ret_text += '\n'.join(repr(x) for x in parse)
    ret_text += '\n' + '==================== AST ======================'
    ast = evaluate_reverse_parse(parse, operations, tokens)
    formatter = FormatVisitor()
    tree = formatter.visit(ast)
    ret_text += '\n' + tree

    ret_text += '\n' + '============== COLLECTING TYPES ==============='
    errors = []
    collector = TypeCollector(errors)
    collector.visit(ast)
    context = collector.context
    ret_text += '\n' + 'Errors:'
    for error in errors:
        ret_text += '\n' + error
    ret_text += '\n' + 'Context:'
    ret_text += '\n' + str(context)
    ret_text += '\n' + '=============== BUILDING TYPES ================'
    builder = TypeBuilder(context, errors)
    builder.visit(ast)
    ret_text += '\n' + 'Errors: ['
    for error in errors:
        ret_text += '\n' + '\t'
        ret_text += '\n' + error
    ret_text += '\n' + ']'
    ret_text += '\n' + 'Context:'
    ret_text += '\n' + str(context)

    ret_text += '\n' + '=============== CHECKING TYPES ================'
    checker = TypeChecker(context, errors)
    try:
        scope, errors = checker.visit(ast)
        while(checker.changed):
            scope, errors = checker.visit(ast)
    except SemanticError as e:
        errors = [e.text]
    ret_text += '\n' + 'Errors: ['
    for error in errors:
        ret_text += '\n' + '\t'
        ret_text += '\n' + error
    ret_text += '\n' + ']'
    if len(errors) == 0:
        checker.printer(ast)

    return ret_text
示例#4
0
    def testBooleanExpressionXor(self):
        (definitions, errors
         ) = Parser().parse("def xor(a, b) = (a and not b) or (not a and b)")
        env = Environment()
        type = TypeChecker().check(errors, env, definitions[0])

        self.assertEqual(errors, [])
        self.assertEqual(str(type), "(Bool, Bool) -> Bool")
示例#5
0
    def testRecursiveFunction(self):
        (definitions, errors) = Parser().parse("""
            def rec(x) = rec(x)
            def value = rec(5)
        """)
        env = Environment()
        id_type = TypeChecker().check(errors, env, definitions[0])
        value_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(id_type), "a -> b")

        # assert correct parsing
        self.assertEqual(str(value_type), "a")
示例#6
0
    def testFirstElementFunction(self):
        (definitions, errors) = Parser().parse("""
            def first(x) = get(x, 0)
            def value = first([5, 6, 6])
        """)
        env = Environment()
        first_type = TypeChecker().check(errors, env, definitions[0])
        value_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(first_type), "[a] -> a")

        # assert correct parsing
        self.assertEqual(str(value_type), "Int")
示例#7
0
    def testFunctionComposition(self):
        (definitions, errors) = Parser().parse("""
            def composition(f, g) = lambda(x) f( g(x) )
            def app = composition(lambda(x) x + 3, lambda(x) x - 4)(10)
        """)
        env = Environment()
        composition_type = TypeChecker().check(errors, env, definitions[0])
        app_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(composition_type), "(a -> b, c -> a) -> c -> b")

        # assert correct parsing
        self.assertEqual(str(app_type), "Int")
示例#8
0
    def testMultipleFunctionApplication(self):
        (definitions, errors) = Parser().parse("""
            def prod = lambda(x) lambda(y) lambda(z) z * y * x
            def value = prod(8)(5)(3)
        """)
        env = Environment()
        prod_type = TypeChecker().check(errors, env, definitions[0])
        value_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(prod_type), "Int -> Int -> Int -> Int")

        # assert correct parsing
        self.assertEqual(str(value_type), "Int")
示例#9
0
    def testPartialFunctionApplication(self):
        (definitions, errors) = Parser().parse("""
            def sum(a) = lambda(b) a + b
            def inc = sum(1)
        """)
        env = Environment()
        sum_type = TypeChecker().check(errors, env, definitions[0])
        inc_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(sum_type), "Int -> Int -> Int")

        # assert correct parsing
        self.assertEqual(str(inc_type), "Int -> Int")
示例#10
0
    def testFunctionApplication(self):
        (definitions, errors) = Parser().parse("""
            def id(x) = x
            def value = id(11)
        """)
        env = Environment()
        id_type = TypeChecker().check(errors, env, definitions[0])
        value_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(id_type), "a -> a")

        # assert correct parsing
        self.assertEqual(str(value_type), "Int")
示例#11
0
    def testFunctionApplicationWithTwoArguments(self):
        (definitions, errors) = Parser().parse("""
            def id(x,y) = y
            def value = id(11, true)
        """)
        env = Environment()
        id_type = TypeChecker().check(errors, env, definitions[0])
        value_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(id_type), "(a, b) -> b")

        # assert correct parsing
        self.assertEqual(str(value_type), "Bool")
示例#12
0
    def testFunctionApplicationWithConstantExpression(self):
        (definitions, errors) = Parser().parse("""
            def id(x,y) = 20
            def value = id(false, true)
        """)
        env = Environment()
        id_type = TypeChecker().check(errors, env, definitions[0])
        value_type = TypeChecker().check(errors, env, definitions[1])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(id_type), "(a, b) -> Int")

        # assert correct parsing
        self.assertEqual(str(value_type), "Int")
示例#13
0
    def testListType(self):
        (definitions, errors) = Parser().parse("def t = [1, 5, 6]")
        type = TypeChecker().check(errors, Environment(), definitions[0])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(type), "[Int]")
示例#14
0
    def testLambdaType(self):
        (definitions, errors) = Parser().parse("def f(x) = lambda(y) x")
        type = TypeChecker().check(errors, Environment(), definitions[0])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(type), "a -> b -> a")
示例#15
0
    def testNegativeIntegerTest(self):
        (definitions, errors) = Parser().parse("def number = -103")
        type = TypeChecker().check(errors, Environment(), definitions[0])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(type), "Int")
示例#16
0
    def testFalseTest(self):
        (definitions, errors) = Parser().parse("def boolean = false")
        type = TypeChecker().check(errors, Environment(), definitions[0])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(type), "Bool")
示例#17
0
    def testVariableType(self):
        (definitions, errors) = Parser().parse("def x = 10")
        type = TypeChecker().check(errors, Environment(), definitions[0])

        # assert that no error occured
        self.assertEqual(errors, [])

        # assert correct parsing
        self.assertEqual(str(type), "Int")
示例#18
0
    def run(self,
            sourceCode,
            filename,
            optimize=True,
            llvmdump=True,
            astDump=True):
        print(formatMessageBoldTitle(f'Compiling {filename}'))
        print(sourceCode)
        try:
            ast = LALRParser(sourceCode)
            TypeChecker(ast).typecheck()
            if astDump is True:
                ast.printFancyTree()

            irModule = LLVMCodeGenerator().generateIR(ast)
            # irModule = exampleIR

            if llvmdump is True:
                print(formatMessageBoldTitle('Unoptimized IR'))
                print(str(irModule))

                outputFilename = './build/output.ll'
                with open(outputFilename, 'w') as llFile:
                    llFile.write(str(irModule))

            # Convert LLVM IR into in-memory representation
            llvmmod = llvm.parse_assembly(str(irModule))

            # Optimize the module
            if optimize:
                pmb = llvm.create_pass_manager_builder()
                pmb.opt_level = 2
                pm = llvm.create_module_pass_manager()
                pmb.populate(pm)
                pm.run(llvmmod)

                if llvmdump is True:
                    print(formatMessageBoldTitle('Optimized IR'))
                    print(str(llvmmod))

            outputFilename = './build/output.o'
            with open(outputFilename, 'wb') as objectFile:
                target_machine = self.target.create_target_machine(
                    codemodel='small')

                # Convert LLVM IR into in-memory representation
                objectCode = target_machine.emit_object(llvmmod)
                objectFile.write(objectCode)

        except CompilationFailure as failure:
            failure.printTrace()
示例#19
0
 def __init__(self,
              start="program",
              outputdir="logs",
              tabmodule="baseparsetab"):
     create_dir(outputdir)
     self.ast = False
     self.type_check = False
     self.scanner = Scanner()
     self.type_checker = TypeChecker()
     self.parser = yacc.yacc(module=self,
                             start=start,
                             tabmodule=tabmodule,
                             outputdir=outputdir)
     self.error = False
示例#20
0
def run(filename, output=True):
    file = open(filename, "r")
    prsr = parser.parser
    text = file.read()
    ast = prsr.parse(text, lexer=scanner.lexer)
    # if ast is not None:
    #     ast.printTree()
    #     print()

    typeChecker = TypeChecker()
    checkRes = typeChecker.visit(ast)
    if output:
        print(checkRes)

    if isinstance(checkRes, Success):
        return ast.accept(Interpreter.Interpreter(output))
示例#21
0
    def __init__(self):
        self.commands = {
            ":type": self.printType,
            ":list": self.printList,
            ":show": self.printDefinition,
            ":code": self.printGeneratedCode,
            ":string": self.setString,
            ":help": lambda x: None,
            "def": self.addDefinition,
        }

        self.printString = False
        self.env = Environment()
        self.checker = TypeChecker()
        self.ghci = GHCI()

        # imports
        self.ghci.execute("import Data.Char")
示例#22
0
def run():
    filename = None
    try:
        filename = sys.argv[1] if len(sys.argv) > 1 else "example1"
        file = open(filename, "r")
    except IOError:
        print("Cannot open {0} file".format(filename))
        sys.exit(0)

    parser = Mparser.parser
    text = file.read()
    lexer.input(text)
    ast = parser.parse(text, lexer=lexer)
    print(ast.printTree())
    typeChecker = TypeChecker()
    typeChecker.visit(ast)  # or alternatively ast.accept(typeChecker)
    print('Checked')

    ast.accept(Interpreter())
示例#23
0
import sys
import ply.yacc as yacc
from Mparser import Mparser
from TreePrinter import TreePrinter
from TypeChecker import TypeChecker

if __name__ == '__main__':
    try:
        filename = sys.argv[1] if len(sys.argv) > 1 else "example.txt"
        file = open(filename, "r")
    except IOError:
        print("Cannot open {0} file".format(filename))
        sys.exit(0)

    Mparser = Mparser()
    parser = yacc.yacc(module=Mparser)
    text = file.read()

    ast = parser.parse(text, lexer=Mparser.scanner)
    typeChecker = TypeChecker()
    typeChecker.visit(ast)  # or alternatively ast.accept(typeChecker)
示例#24
0
import sys
import ply.yacc as yacc
from Cparser import Cparser
from TypeChecker import TypeChecker
from Interpreter import Interpreter

if __name__ == '__main__':

    try:
        filename = sys.argv[1] if len(sys.argv) > 1 else "example.txt"
        file = open(filename, "r")
    except IOError:
        print("Cannot open {0} file".format(filename))
        sys.exit(0)

    Cparser = Cparser()
    parser = yacc.yacc(module=Cparser)
    text = file.read()

    ast = parser.parse(text, lexer=Cparser.scanner)
    if ast.accept(TypeChecker()):
        # jesli wizytor TypeChecker z implementacji w poprzednim lab korzystal z funkcji accept
        # to nazwa tej ostatniej dla Interpretera powinna zostac zmieniona, np. na accept2 ( ast.accept2(Interpreter()) )
        # tak aby rozne funkcje accept z roznych implementacji wizytorow nie kolidowaly ze soba
        ast.accept(Interpreter())

    # in future
    # ast.accept(OptimizationPass1())
    # ast.accept(OptimizationPass2())
    # ast.accept(CodeGenerator())
示例#25
0
def typechecker_passes(text: str):
    ast = parser.parse(text)
    typechecker = TypeChecker()
    typechecker.visit(ast)
    return typechecker.errorok
示例#26
0
def typechecker_fails(text: str):
    ast = parser.parse(text)
    typechecker = TypeChecker()
    typechecker.visit(ast)
    return not typechecker.errorok
示例#27
0
import Mparser
from TreePrinter import TreePrinter
from TreeGrapher import draw_tree_from_text
from TypeChecker import TypeChecker

if __name__ == '__main__':
    filename = sys.argv[1] if len(sys.argv) > 1 else "example1.m"

    try:
        file = open(filename, "r")
    except IOError:
        print("Cannot open {0} file".format(filename))
        sys.exit(0)

    parser = Mparser.parser
    text = file.read()
    ast = parser.parse(text, lexer=scanner.lexer, tracking=True)

    # tree_text = ast.printTree()
    # print(tree_text)
    # draw_tree_from_text(tree_text, 'graph')

    tc = TypeChecker()
    tc.visit(ast)
    if tc.error_counter == 0:
        print("No errors found")
    elif tc.error_counter == 1:
        print("! 1 error found")
    else:
        print(f"! {tc.error_counter} errors found")