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)
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")
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
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")
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")
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")
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")
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")
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")
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")
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")
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")
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]")
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")
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")
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")
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")
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()
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
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))
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")
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())
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)
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())
def typechecker_passes(text: str): ast = parser.parse(text) typechecker = TypeChecker() typechecker.visit(ast) return typechecker.errorok
def typechecker_fails(text: str): ast = parser.parse(text) typechecker = TypeChecker() typechecker.visit(ast) return not typechecker.errorok
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")