diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index b854115b4b..94f6cc469f 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -694,7 +694,8 @@ RUN(NAME global_syms_04 LABELS cpython llvm c wasm wasm_x64) RUN(NAME global_syms_05 LABELS cpython llvm c) RUN(NAME global_syms_06 LABELS cpython llvm c) -RUN(NAME callback_01 LABELS cpython llvm) +RUN(NAME callback_01 LABELS cpython llvm c) +RUN(NAME callback_02 LABELS cpython llvm c) # Intrinsic Functions RUN(NAME intrinsics_01 LABELS cpython llvm NOFAST) # any diff --git a/integration_tests/callback_02.py b/integration_tests/callback_02.py new file mode 100644 index 0000000000..330f75cbbf --- /dev/null +++ b/integration_tests/callback_02.py @@ -0,0 +1,18 @@ +from lpython import ccallback, i32, Callable + +# test issue 2169 + +def foo(x : i32) -> i32: + return x**2 + +def bar(func : Callable[[i32], i32], arg : i32) -> i32: + return func(arg) + +@ccallback +def entry_point() -> None: + z: i32 = 5 + x: i32 = bar(foo, z) + assert z**2 == x + + +entry_point() diff --git a/src/libasr/codegen/asr_to_c.cpp b/src/libasr/codegen/asr_to_c.cpp index a63f5098c3..f25d565c46 100644 --- a/src/libasr/codegen/asr_to_c.cpp +++ b/src/libasr/codegen/asr_to_c.cpp @@ -739,8 +739,8 @@ R"( array_types_decls.insert(0, "struct dimension_descriptor\n" "{\n int32_t lower_bound, length;\n};\n"); } - - src = to_include + head + array_types_decls + unit_src + + forward_decl_functions += "\n\n"; + src = to_include + head + array_types_decls + forward_decl_functions + unit_src + ds_funcs_defined + util_funcs_defined; if (!emit_headers.empty()) { std::string to_includes_1 = ""; diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index e4b631d7a1..4de1a78c31 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -137,6 +137,7 @@ class BaseCCPPVisitor : public ASR::BaseVisitor std::map gotoid2name; std::map emit_headers; std::string array_types_decls; + std::string forward_decl_functions; // Output configuration: // Use std::string or char* @@ -493,7 +494,7 @@ R"(#include } // Returns the declaration, no semi colon at the end - std::string get_function_declaration(const ASR::Function_t &x, bool &has_typevar) { + std::string get_function_declaration(const ASR::Function_t &x, bool &has_typevar, bool is_pointer=false) { template_for_Kokkos.clear(); template_number = 0; std::string sub, inl, static_attr; @@ -501,10 +502,10 @@ R"(#include // This helps to check if the function is generic. // If it is generic we skip the codegen for that function. has_typevar = false; - if (ASRUtils::get_FunctionType(x)->m_inline) { + if (ASRUtils::get_FunctionType(x)->m_inline && !is_pointer) { inl = "inline __attribute__((always_inline)) "; } - if( ASRUtils::get_FunctionType(x)->m_static ) { + if( ASRUtils::get_FunctionType(x)->m_static && !is_pointer) { static_attr = "static "; } if (x.m_return_var) { @@ -526,30 +527,47 @@ R"(#include f_type->m_deftype == ASR::deftypeType::Implementation) { sym_name = "_xx_internal_" + sym_name + "_xx"; } - std::string func = static_attr + inl + sub + sym_name + "("; + std::string func = static_attr + inl + sub; + if (is_pointer) { + func += "(*" + sym_name + ")("; + } else { + func += sym_name + "("; + } bracket_open++; for (size_t i=0; im_intent)); - if (ASR::is_a(*arg->m_type)) { - has_typevar = true; - bracket_open--; - return ""; - } - if( is_c ) { - CDeclarationOptions c_decl_options; - c_decl_options.pre_initialise_derived_type = false; - func += self().convert_variable_decl(*arg, &c_decl_options); + ASR::symbol_t *sym = ASRUtils::symbol_get_past_external( + ASR::down_cast(x.m_args[i])->m_v); + if (ASR::is_a(*sym)) { + ASR::Variable_t *arg = ASR::down_cast(sym); + LCOMPILERS_ASSERT(ASRUtils::is_arg_dummy(arg->m_intent)); + if( is_c ) { + CDeclarationOptions c_decl_options; + c_decl_options.pre_initialise_derived_type = false; + func += self().convert_variable_decl(*arg, &c_decl_options); + } else { + CPPDeclarationOptions cpp_decl_options; + cpp_decl_options.use_static = false; + cpp_decl_options.use_templates_for_arrays = true; + func += self().convert_variable_decl(*arg, &cpp_decl_options); + } + if (ASR::is_a(*arg->m_type)) { + has_typevar = true; + bracket_open--; + return ""; + } + } else if (ASR::is_a(*sym)) { + ASR::Function_t *fun = ASR::down_cast(sym); + func += get_function_declaration(*fun, has_typevar, true); } else { - CPPDeclarationOptions cpp_decl_options; - cpp_decl_options.use_static = false; - cpp_decl_options.use_templates_for_arrays = true; - func += self().convert_variable_decl(*arg, &cpp_decl_options); + throw CodeGenError("Unsupported function argument"); } if (i < x.n_args-1) func += ", "; } func += ")"; bracket_open--; + if (f_type->m_abi == ASR::abiType::Source) { + forward_decl_functions += func + ";\n"; + } if( is_c || template_for_Kokkos.empty() ) { return func; } @@ -1716,6 +1734,10 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { void visit_Var(const ASR::Var_t &x) { const ASR::symbol_t *s = ASRUtils::symbol_get_past_external(x.m_v); + if (ASR::is_a(*s)) { + src = ASRUtils::symbol_name(s); + return; + } ASR::Variable_t* sv = ASR::down_cast(s); if( (sv->m_intent == ASRUtils::intent_in || sv->m_intent == ASRUtils::intent_inout) && diff --git a/tests/reference/c-c_interop1-e215531.json b/tests/reference/c-c_interop1-e215531.json index 8728b3498c..9cd8533dac 100644 --- a/tests/reference/c-c_interop1-e215531.json +++ b/tests/reference/c-c_interop1-e215531.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-c_interop1-e215531.stdout", - "stdout_hash": "31d7d540adfef1263741e1b9709e4a2a73c6208147d735906dbf233e", + "stdout_hash": "9d9dd1715b625024203f8b4de330a936a806c5e8031ae7b643c23e71", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-c_interop1-e215531.stdout b/tests/reference/c-c_interop1-e215531.stdout index 3086db2be0..60c6da2270 100644 --- a/tests/reference/c-c_interop1-e215531.stdout +++ b/tests/reference/c-c_interop1-e215531.stdout @@ -7,6 +7,8 @@ #include + + // Implementations double f(double x); diff --git a/tests/reference/c-expr7-bb2692a.json b/tests/reference/c-expr7-bb2692a.json index 550f459161..036167509f 100644 --- a/tests/reference/c-expr7-bb2692a.json +++ b/tests/reference/c-expr7-bb2692a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-expr7-bb2692a.stdout", - "stdout_hash": "be3bac9bcf7f1fab11741c22151820f60793d5afc670486e9d0913aa", + "stdout_hash": "11026dff0f543f773698075edb3d690f8a475e8639124f1e1dcaef6a", "stderr": "c-expr7-bb2692a.stderr", "stderr_hash": "6e9790ac88db1a9ead8f64a91ba8a6605de67167037908a74b77be0c", "returncode": 0 diff --git a/tests/reference/c-expr7-bb2692a.stdout b/tests/reference/c-expr7-bb2692a.stdout index b0535e0a22..11b1ed1456 100644 --- a/tests/reference/c-expr7-bb2692a.stdout +++ b/tests/reference/c-expr7-bb2692a.stdout @@ -8,6 +8,12 @@ #include #include +void test_pow(); +int32_t test_pow_1(int32_t a, int32_t b); +void main0(); +void __main____global_statements(); + + // Implementations double __lpython_overloaded_0__pow(int32_t x, int32_t y) diff --git a/tests/reference/c-expr_01-28f449f.json b/tests/reference/c-expr_01-28f449f.json index baa657a5d0..e825e50b18 100644 --- a/tests/reference/c-expr_01-28f449f.json +++ b/tests/reference/c-expr_01-28f449f.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-expr_01-28f449f.stdout", - "stdout_hash": "21755da8aacbb21ee5a5229c8f47f7ba40c36d942af84f848e36bd5b", + "stdout_hash": "b9e6df09a73026d76ea9eefed3e2b211476b1ac55956ee8150a4a417", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-expr_01-28f449f.stdout b/tests/reference/c-expr_01-28f449f.stdout index 3a608760f9..11fd1f1ff2 100644 --- a/tests/reference/c-expr_01-28f449f.stdout +++ b/tests/reference/c-expr_01-28f449f.stdout @@ -6,6 +6,12 @@ #include #include +inline __attribute__((always_inline)) int32_t add(int32_t x, int32_t y); +inline __attribute__((always_inline)) int32_t and_op(int32_t x, int32_t y); +void main0(); +void __main____global_statements(); + + // Implementations inline __attribute__((always_inline)) int32_t add(int32_t x, int32_t y) diff --git a/tests/reference/c-expr_11-c452314.json b/tests/reference/c-expr_11-c452314.json index add507f463..1393264d39 100644 --- a/tests/reference/c-expr_11-c452314.json +++ b/tests/reference/c-expr_11-c452314.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-expr_11-c452314.stdout", - "stdout_hash": "3566609825322587b3a725aa627c191e47e28835a78f182bb95546ab", + "stdout_hash": "828e55148962eac31cff8246dbf28003a81b9852481aa1e584128ecb", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-expr_11-c452314.stdout b/tests/reference/c-expr_11-c452314.stdout index 4b9efc3750..81a2868d08 100644 --- a/tests/reference/c-expr_11-c452314.stdout +++ b/tests/reference/c-expr_11-c452314.stdout @@ -6,6 +6,10 @@ #include #include +void f(); +void __main____global_statements(); + + // Implementations void f() diff --git a/tests/reference/c-expr_12-93c7780.json b/tests/reference/c-expr_12-93c7780.json index ecf8b69e35..11969c5667 100644 --- a/tests/reference/c-expr_12-93c7780.json +++ b/tests/reference/c-expr_12-93c7780.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-expr_12-93c7780.stdout", - "stdout_hash": "094a6e7284485e456d1ff691266f3ab0400f2893e1e7670fb186cf6b", + "stdout_hash": "4ff750b49402a8f60ae61abdc16289388dfb3230995dda8b75fcd8cd", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-expr_12-93c7780.stdout b/tests/reference/c-expr_12-93c7780.stdout index 1a6a72ed9c..567498a526 100644 --- a/tests/reference/c-expr_12-93c7780.stdout +++ b/tests/reference/c-expr_12-93c7780.stdout @@ -19,6 +19,12 @@ struct i16 bool is_allocated; }; +void g(struct i16* *x, struct i16* y); +void check(struct i16* *ptr); +void f(); +void __main____global_statements(); + + // Implementations void g(struct i16* *x, struct i16* y) diff --git a/tests/reference/c-func_static_01-fc146ec.json b/tests/reference/c-func_static_01-fc146ec.json index fd78ebffa1..a115a734b8 100644 --- a/tests/reference/c-func_static_01-fc146ec.json +++ b/tests/reference/c-func_static_01-fc146ec.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-func_static_01-fc146ec.stdout", - "stdout_hash": "ee924027aed46d89fab1ee33f7bb07aa925c27f272bb7e8766e9f63d", + "stdout_hash": "77431288e9f3af7e7f5d2a2859ade52772a79789337db403b3dc9943", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-func_static_01-fc146ec.stdout b/tests/reference/c-func_static_01-fc146ec.stdout index 7b80ac8575..71e33ca7e4 100644 --- a/tests/reference/c-func_static_01-fc146ec.stdout +++ b/tests/reference/c-func_static_01-fc146ec.stdout @@ -6,6 +6,11 @@ #include #include +static int64_t fib(int64_t n); +void main0(); +void __main____global_statements(); + + // Implementations static int64_t fib(int64_t n) diff --git a/tests/reference/c-import_order_01-3ebf3c3.json b/tests/reference/c-import_order_01-3ebf3c3.json index 4d63dfe8f5..8a602aa1fc 100644 --- a/tests/reference/c-import_order_01-3ebf3c3.json +++ b/tests/reference/c-import_order_01-3ebf3c3.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-import_order_01-3ebf3c3.stdout", - "stdout_hash": "63a56ec5425b877465861abc207045ed30f150f6ab78004a2243433d", + "stdout_hash": "f3e4798c2ffb4df885977927d38d89b0354c812264ae40b4e7103ced", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-import_order_01-3ebf3c3.stdout b/tests/reference/c-import_order_01-3ebf3c3.stdout index b398b0346a..3a50069788 100644 --- a/tests/reference/c-import_order_01-3ebf3c3.stdout +++ b/tests/reference/c-import_order_01-3ebf3c3.stdout @@ -6,6 +6,9 @@ #include #include +int32_t f(); + + // Implementations int32_t f() diff --git a/tests/reference/c-loop1-3e341c7.json b/tests/reference/c-loop1-3e341c7.json index 71b0449c8b..48914d1096 100644 --- a/tests/reference/c-loop1-3e341c7.json +++ b/tests/reference/c-loop1-3e341c7.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-loop1-3e341c7.stdout", - "stdout_hash": "63eae4287cec6a9ae5a1b3f5aacaddc08eb7edc0fa9ff7589c3ebc31", + "stdout_hash": "241f7395d191f7dd26195e71200be7e23a30969f2cca993137eb8b2d", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-loop1-3e341c7.stdout b/tests/reference/c-loop1-3e341c7.stdout index e27b8cfd45..a6666fb464 100644 --- a/tests/reference/c-loop1-3e341c7.stdout +++ b/tests/reference/c-loop1-3e341c7.stdout @@ -6,6 +6,13 @@ #include #include +int32_t test_factorial_1(int32_t x); +int32_t test_factorial_2(int32_t x); +int64_t test_factorial_3(int32_t x); +void main0(); +void __main____global_statements(); + + // Implementations int32_t test_factorial_1(int32_t x) diff --git a/tests/reference/c-loop4-eec10d3.json b/tests/reference/c-loop4-eec10d3.json index 66986ff877..053e2c96ab 100644 --- a/tests/reference/c-loop4-eec10d3.json +++ b/tests/reference/c-loop4-eec10d3.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-loop4-eec10d3.stdout", - "stdout_hash": "dd37ec60eb4710dc87766a78d83b77dcb982672d291848eb82c45814", + "stdout_hash": "9c6c8fd97e7c24685ba75f6037f45993f3f739817b4fb6650cd9cab8", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-loop4-eec10d3.stdout b/tests/reference/c-loop4-eec10d3.stdout index fb68fc33ba..2b73748426 100644 --- a/tests/reference/c-loop4-eec10d3.stdout +++ b/tests/reference/c-loop4-eec10d3.stdout @@ -6,6 +6,10 @@ #include #include +void test_for(); +void __main____global_statements(); + + // Implementations void test_for() diff --git a/tests/reference/c-print_01-4d44628.json b/tests/reference/c-print_01-4d44628.json index 9ce64802c0..46a9147135 100644 --- a/tests/reference/c-print_01-4d44628.json +++ b/tests/reference/c-print_01-4d44628.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-print_01-4d44628.stdout", - "stdout_hash": "a42a087d40d750b53b9bc6ac7c8248c05b5adb253addd2c0a0d47550", + "stdout_hash": "eeedca2639797a26c43f22383f01cdd16382d27921d87a70687c44d9", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-print_01-4d44628.stdout b/tests/reference/c-print_01-4d44628.stdout index 028516f5e9..a01b63f3f0 100644 --- a/tests/reference/c-print_01-4d44628.stdout +++ b/tests/reference/c-print_01-4d44628.stdout @@ -5,6 +5,10 @@ #include #include +void f(); +void __main____global_statements(); + + // Implementations void f() diff --git a/tests/reference/c-test_import_02-d2c54c4.json b/tests/reference/c-test_import_02-d2c54c4.json index 6f8396ea92..860ef73744 100644 --- a/tests/reference/c-test_import_02-d2c54c4.json +++ b/tests/reference/c-test_import_02-d2c54c4.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-test_import_02-d2c54c4.stdout", - "stdout_hash": "62cb9cf8e988af42d9375f49577532a91ab0c9bde8f9a9ce62c3f691", + "stdout_hash": "96649585d0a2f2f8e55f872b58bb924983457db3679b43525112a3ec", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-test_import_02-d2c54c4.stdout b/tests/reference/c-test_import_02-d2c54c4.stdout index d8f2b6e7c1..5a00396496 100644 --- a/tests/reference/c-test_import_02-d2c54c4.stdout +++ b/tests/reference/c-test_import_02-d2c54c4.stdout @@ -6,6 +6,12 @@ #include #include +int32_t add(int32_t x, int32_t y); +int32_t multiply(int32_t x, int32_t y); +void f(); +void __main____global_statements(); + + // Implementations const double μ = 1.45136923488338110e+00; diff --git a/tests/reference/c-test_issue_518-fbbd299.json b/tests/reference/c-test_issue_518-fbbd299.json index 82b2e470c5..49d711d264 100644 --- a/tests/reference/c-test_issue_518-fbbd299.json +++ b/tests/reference/c-test_issue_518-fbbd299.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-test_issue_518-fbbd299.stdout", - "stdout_hash": "f744351df831c8870f53e3a5eefbdf47df6716a1152b2f0bda2c2cfd", + "stdout_hash": "651a207e618ca25fb733b618072bd3586b652da51a824ddd03d681d1", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-test_issue_518-fbbd299.stdout b/tests/reference/c-test_issue_518-fbbd299.stdout index 8dd3ea99b2..017b91c120 100644 --- a/tests/reference/c-test_issue_518-fbbd299.stdout +++ b/tests/reference/c-test_issue_518-fbbd299.stdout @@ -6,6 +6,12 @@ #include #include +int64_t fib(int64_t n); +void main0(); +void _xx_lcompilers_changed_main_xx(); +void __main____global_statements(); + + // Implementations int64_t fib(int64_t n) diff --git a/tests/reference/c-variable_decl_03-fa1823b.json b/tests/reference/c-variable_decl_03-fa1823b.json index fe83d99fe6..a6b8f62335 100644 --- a/tests/reference/c-variable_decl_03-fa1823b.json +++ b/tests/reference/c-variable_decl_03-fa1823b.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "c-variable_decl_03-fa1823b.stdout", - "stdout_hash": "6b7c50e825519137edd2df53a8926974c90b3dd88697761cd640f449", + "stdout_hash": "c6088ef2edb0ff2113dad651f6f782fb8dfdbe32a563d25eaa8eb0b4", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/c-variable_decl_03-fa1823b.stdout b/tests/reference/c-variable_decl_03-fa1823b.stdout index 87b23fad4d..a2ef090474 100644 --- a/tests/reference/c-variable_decl_03-fa1823b.stdout +++ b/tests/reference/c-variable_decl_03-fa1823b.stdout @@ -5,6 +5,12 @@ #include #include +double _lcompilers_abs_f64(double x); +double f(); +void _xx_lcompilers_changed_main_xx(); +void __main____global_statements(); + + // Implementations double _lcompilers_abs_f64(double x)