def testExpressionMultiplicationPrecedence(self): ast = Parser().parseTopLevel('2+3*4-9') self._assertBody(ast, [ 'Binop', '-', [ 'Binop', '+', ['Double', '2'], ['Binop', '*', ['Double', '3'], ['Double', '4']] ], ['Double', '9'] ])
def testFunctionDefinition(self): ast = Parser().parseTopLevel('func foo(x) 1 + bar(x)') self.assertEqual(self._flatten(ast), [ 'Function', ['Proto', 'foo', 'x'], [ 'Binop', '+', ['Double', '1'], ['Call', 'bar', [['Variable', 'x']]] ] ])
def testExpressionParentheses(self): ast = Parser().parseTopLevel('2*(3-4)*7') self._assertBody(ast, [ 'Binop', '*', [ 'Binop', '*', ['Double', '2'], ['Binop', '-', ['Double', '3'], ['Double', '4']] ], ['Double', '7'] ])
def evaluate(self, codeString, optimize=True, llvmdump=False): """ Evaluate code in codestr. Returns 0.0 for definitions and import, and the evaluated expression value for toplevel expressions. """ # Parse the given code and generate code from it ast = Parser().parseTopLevel(codeString) self.codegen.generateCode(ast) test = type(ast) if llvmdump: print('======== Unoptimized LLVM IR') print(str(self.codegen.module)) # If we're evaluating a definition or import declaration, don't do # anything else. If we're evaluating an anonymous wrapper for a toplevel # expression, JIT-compile the module and run the function to get its # result. llvmmod = llvm.parse_assembly(str(self.codegen.module)) #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: print('======== Optimized LLVM IR') print(str(llvmmod)) # Create a MCJIT execution engine to JIT-compile the module. Note that # ee takes ownership of target_machine, so it has to be recreated anew # each time we call create_mcjit_compiler. targetMachine = self.target.create_target_machine() with llvm.create_mcjit_compiler(llvmmod, targetMachine) as mcjitCompiler: mcjitCompiler.finalize_object() if llvmdump: print('======== Machine code') print(targetMachine.emit_assembly(llvmmod)) result = 0.0 if type(ast) == FunctionAST: functionPointer = CFUNCTYPE(c_double)( mcjitCompiler.get_function_address(ast.proto.name)) result = functionPointer() return result
def testExpressionSinglePrecedent(self): ast = Parser().parseTopLevel('2 + 3 - 4') self._assertBody(ast, [ 'Binop', '-', ['Binop', '+', ['Double', '2'], ['Double', '3']], ['Double', '4'] ])
def testBasicWithFlattening(self): ast = Parser().parseTopLevel('2') self._assertBody(ast, ['Double', '2']) ast = Parser().parseTopLevel('foobar') self._assertBody(ast, ['Variable', 'foobar'])
def testBasic(self): ast = Parser().parseTopLevel('2') self.assertIsInstance(ast, FunctionAST) self.assertIsInstance(ast.body, DoubleExprAST) self.assertEqual(ast.body.val, '2')
def testImports(self): ast = Parser().parseTopLevel('import sin(arg)') self.assertEqual(self._flatten(ast), ['Proto', 'sin', 'arg']) ast = Parser().parseTopLevel('import Foobar(nom denom abom)') self.assertEqual(self._flatten(ast), ['Proto', 'Foobar', 'nom denom abom'])