def test_FunctionPrototype_and_FunctionDefinition(): vx = Variable(x, type=real) vn = Variable(n, type=integer) fp1 = FunctionPrototype(real, 'power', [vx, vn]) assert fp1.return_type == real assert fp1.name == String('power') assert fp1.parameters == Tuple(vx, vn) assert fp1 == FunctionPrototype(real, 'power', [vx, vn]) assert fp1 != FunctionPrototype(real, 'power', [vn, vx]) assert fp1.func(*fp1.args) == fp1 body = [Assignment(x, x**n), Return(x)] fd1 = FunctionDefinition(real, 'power', [vx, vn], body) assert fd1.return_type == real assert str(fd1.name) == 'power' assert fd1.parameters == Tuple(vx, vn) assert fd1.body == CodeBlock(*body) assert fd1 == FunctionDefinition(real, 'power', [vx, vn], body) assert fd1 != FunctionDefinition(real, 'power', [vx, vn], body[::-1]) assert fd1.func(*fd1.args) == fd1 fp2 = FunctionPrototype.from_FunctionDefinition(fd1) assert fp2 == fp1 fd2 = FunctionDefinition.from_FunctionPrototype(fp1, body) assert fd2 == fd1
def test_ccode_codegen_ast(): assert ccode(Comment("this is a comment")) == "// this is a comment" assert ccode(While(abs(x) > 1, [aug_assign(x, '-', 1)])) == ('while (fabs(x) > 1) {\n' ' x -= 1;\n' '}') assert ccode(Scope([AddAugmentedAssignment(x, 1)])) == ('{\n' ' x += 1;\n' '}') inp_x = Declaration(Variable(x, type=real)) assert ccode(FunctionPrototype(real, 'pwer', [inp_x])) == 'double pwer(double x)' assert ccode( FunctionDefinition( real, 'pwer', [inp_x], [Assignment(x, x**2)])) == ('double pwer(double x){\n' ' x = pow(x, 2);\n' '}') # Elements of CodeBlock are formatted as statements: block = CodeBlock( x, Print([x, y], "%d %d"), FunctionCall('pwer', [x]), Return(x), ) assert ccode(block) == '\n'.join([ 'x;', 'printf("%d %d", x, y);', 'pwer(x);', 'return x;', ])
def test_function(): c_src1 = "void fun1()" + "\n" + "{" + "\n" + "int a;" + "\n" + "}" c_src2 = ("int fun2()" + "\n" + "{" + "\n" + "int a;" + "\n" + "return a;" + "\n" + "}") c_src3 = ("float fun3()" + "\n" + "{" + "\n" + "float b;" + "\n" + "return b;" + "\n" + "}") c_src4 = "float fun4()" + "\n" + "{}" res1 = SymPyExpression(c_src1, "c").return_expr() res2 = SymPyExpression(c_src2, "c").return_expr() res3 = SymPyExpression(c_src3, "c").return_expr() res4 = SymPyExpression(c_src4, "c").return_expr() assert res1[0] == FunctionDefinition( NoneToken(), name=String("fun1"), parameters=(), body=CodeBlock( Declaration( Variable( Symbol("a"), type=IntBaseType(String("integer")), value=Integer(0), ))), ) assert res2[0] == FunctionDefinition( IntBaseType(String("integer")), name=String("fun2"), parameters=(), body=CodeBlock( Declaration( Variable( Symbol("a"), type=IntBaseType(String("integer")), value=Integer(0), )), Return("a"), ), ) assert res3[0] == FunctionDefinition( FloatBaseType(String("real")), name=String("fun3"), parameters=(), body=CodeBlock( Declaration( Variable( Symbol("b"), type=FloatBaseType(String("real")), value=Float("0.0", precision=53), )), Return("b"), ), ) assert res4[0] == FunctionPrototype(FloatBaseType(String("real")), name=String("fun4"), parameters=())
def test_FunctionPrototype_print(): x = symbols('x') n = symbols('n', integer=True) vx = Variable(x, type=real) vn = Variable(n, type=integer) fp1 = FunctionPrototype(real, 'power', [vx, vn]) # Should be changed to proper test once multi-line generation is working # see https://github.com/sympy/sympy/issues/15824 raises(NotImplementedError, lambda: fcode(fp1))
def _render_compile_import(funcdef, build_dir): code_str = render_as_source_file(funcdef, settings=dict(contract=False)) declar = ccode(FunctionPrototype.from_FunctionDefinition(funcdef)) return compile_link_import_strings( [('our_test_func.c', code_str), ('_our_test_func.pyx', ("cdef extern {declar}\n" "def _{fname}({typ}[:] inp, {typ}[:] out):\n" " {fname}(inp.size, &inp[0], &out[0])").format( declar=declar, fname=funcdef.name, typ='double'))], build_dir=build_dir)
def _render_compile_import(funcdef, build_dir): code_str = render_as_source_file(funcdef, settings=dict(contract=False)) declar = ccode(FunctionPrototype.from_FunctionDefinition(funcdef)) return compile_link_import_strings([ ('our_test_func.c', code_str), ('_our_test_func.pyx', ("cdef extern {declar}\n" "def _{fname}({typ}[:] inp, {typ}[:] out):\n" " {fname}(inp.size, &inp[0], &out[0])").format( declar=declar, fname=funcdef.name, typ='double' )) ], build_dir=build_dir)
def test_ccode_codegen_ast(): assert ccode(Comment("this is a comment")) == "// this is a comment" assert ccode(While(abs(x) > 1, [aug_assign(x, "-", 1)])) == ( "while (fabs(x) > 1) {\n" " x -= 1;\n" "}" ) assert ccode(Scope([AddAugmentedAssignment(x, 1)])) == ("{\n" " x += 1;\n" "}") inp_x = Declaration(Variable(x, type=real)) assert ccode(FunctionPrototype(real, "pwer", [inp_x])) == "double pwer(double x)" assert ccode( FunctionDefinition(real, "pwer", [inp_x], [Assignment(x, x ** 2)]) ) == ("double pwer(double x){\n" " x = pow(x, 2);\n" "}") # Elements of CodeBlock are formatted as statements: block = CodeBlock(x, Print([x, y], "%d %d"), FunctionCall("pwer", [x]), Return(x),) assert ccode(block) == "\n".join( ["x;", 'printf("%d %d", x, y);', "pwer(x);", "return x;",] )
def _render_compile_import(funcdef, build_dir): code_str = render_as_source_file(funcdef, settings=dict(contract=False)) declar = ccode(FunctionPrototype.from_FunctionDefinition(funcdef)) return compile_link_import_strings( [ ("our_test_func.c", code_str), ( "_our_test_func.pyx", ("#cython: language_level={}\n".format("3") + "cdef extern {declar}\n" "def _{fname}({typ}[:] inp, {typ}[:] out):\n" " {fname}(inp.size, &inp[0], &out[0])").format( declar=declar, fname=funcdef.name, typ="double"), ), ], build_dir=build_dir, )
def test_function(): c_src1 = ('void fun1()' + '\n' + '{' + '\n' + 'int a;' + '\n' + '}') c_src2 = ('int fun2()' + '\n' + '{' + '\n' + 'int a;' + '\n' + 'return a;' + '\n' + '}') c_src3 = ('float fun3()' + '\n' + '{' + '\n' + 'float b;' + '\n' + 'return b;' + '\n' + '}') c_src4 = ('float fun4()' + '\n' + '{}') res1 = SymPyExpression(c_src1, 'c').return_expr() res2 = SymPyExpression(c_src2, 'c').return_expr() res3 = SymPyExpression(c_src3, 'c').return_expr() res4 = SymPyExpression(c_src4, 'c').return_expr() assert res1[0] == FunctionDefinition( NoneToken(), name=String('fun1'), parameters=(), body=CodeBlock( Declaration( Variable(Symbol('a'), type=IntBaseType(String('integer')), value=Integer(0))))) assert res2[0] == FunctionDefinition( IntBaseType(String('integer')), name=String('fun2'), parameters=(), body=CodeBlock( Declaration( Variable(Symbol('a'), type=IntBaseType(String('integer')), value=Integer(0))), Return('a'))) assert res3[0] == FunctionDefinition( FloatBaseType(String('real')), name=String('fun3'), parameters=(), body=CodeBlock( Declaration( Variable(Symbol('b'), type=FloatBaseType(String('real')), value=Float('0.0', precision=53))), Return('b'))) assert res4[0] == FunctionPrototype(FloatBaseType(String('real')), name=String('fun4'), parameters=())
def test_ccode_codegen_ast(): # Note that C only allows comments of the form /* ... */, double forward # slash is not standard C, and some C compilers will grind to a halt upon # encountering them. assert ccode( Comment("this is a comment")) == "/* this is a comment */" # not // assert ccode(While(abs(x) > 1, [aug_assign(x, '-', 1)])) == ('while (fabs(x) > 1) {\n' ' x -= 1;\n' '}') assert ccode(Scope([AddAugmentedAssignment(x, 1)])) == ('{\n' ' x += 1;\n' '}') inp_x = Declaration(Variable(x, type=real)) assert ccode(FunctionPrototype(real, 'pwer', [inp_x])) == 'double pwer(double x)' assert ccode( FunctionDefinition( real, 'pwer', [inp_x], [Assignment(x, x**2)])) == ('double pwer(double x){\n' ' x = pow(x, 2);\n' '}') # Elements of CodeBlock are formatted as statements: block = CodeBlock( x, Print([x, y], "%d %d"), FunctionCall('pwer', [x]), Return(x), ) assert ccode(block) == '\n'.join([ 'x;', 'printf("%d %d", x, y);', 'pwer(x);', 'return x;', ])
def transform_function_decl(self, node): """Transformation Function For Function Declaration Used to create nodes for function declarations and definitions for the respective nodes in the clang AST Returns ======= function : Codegen AST node - FunctionPrototype node if function body is not present - FunctionDefinition node if the function body is present """ if node.result_type.kind in self._data_types["int"]: ret_type = self._data_types["int"][node.result_type.kind] elif node.result_type.kind in self._data_types["float"]: ret_type = self._data_types["float"][node.result_type.kind] elif node.result_type.kind in self._data_types["bool"]: ret_type = self._data_types["bool"][node.result_type.kind] elif node.result_type.kind in self._data_types["void"]: ret_type = self._data_types["void"][node.result_type.kind] else: raise NotImplementedError("Only void, bool, int " "and float are supported") body = [] param = [] try: children = node.get_children() child = next(children) # If the node has any children, the first children will be the # return type and namespace for the function declaration. These # nodes can be ignored. while child.kind == cin.CursorKind.NAMESPACE_REF: child = next(children) while child.kind == cin.CursorKind.TYPE_REF: child = next(children) # Subsequent nodes will be the parameters for the function. try: while True: decl = self.transform(child) if (child.kind == cin.CursorKind.PARM_DECL): param.append(decl) elif (child.kind == cin.CursorKind.COMPOUND_STMT): for val in decl: body.append(val) else: body.append(decl) child = next(children) except StopIteration: pass except StopIteration: pass if body == []: function = FunctionPrototype( return_type = ret_type, name = node.spelling, parameters = param ) else: function = FunctionDefinition( return_type = ret_type, name = node.spelling, parameters = param, body = body ) return function
def transform_function_decl(self, node): """Transformation Function For Function Declaration Used to create nodes for function declarations and definitions for the respective nodes in the clang AST Returns ======= function : Codegen AST node - FunctionPrototype node if function body is not present - FunctionDefinition node if the function body is present """ token = node.get_tokens() c_ret_type = next(token).spelling if (c_ret_type == 'void'): ret_type = none elif (c_ret_type == 'int'): ret_type = IntBaseType(String('integer')) elif (c_ret_type == 'float'): ret_type = FloatBaseType(String('real')) else: raise NotImplementedError("Variable not yet supported") body = [] param = [] try: children = node.get_children() child = next(children) # If the node has any children, the first children will be the # return type and namespace for the function declaration. These # nodes can be ignored. while child.kind == cin.CursorKind.NAMESPACE_REF: child = next(children) while child.kind == cin.CursorKind.TYPE_REF: child = next(children) # Subsequent nodes will be the parameters for the function. try: while True: decl = self.transform(child) if (child.kind == cin.CursorKind.PARM_DECL): param.append(decl) elif (child.kind == cin.CursorKind.COMPOUND_STMT): for val in decl: body.append(val) else: body.append(decl) child = next(children) except StopIteration: pass except StopIteration: pass if body == []: function = FunctionPrototype(return_type=ret_type, name=node.spelling, parameters=param) else: function = FunctionDefinition(return_type=ret_type, name=node.spelling, parameters=param, body=body) return function