From 8b991b158417aa21f0b0d8fa87af53df90272744 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 8 Nov 2024 11:59:31 +0300 Subject: [PATCH] checker: auto generate missing C function definitions --- vlib/v/checker/fn.v | 30 +++++++++++++++++++ .../tests/include_c_gen_fn_headers/cheader.h | 9 ++++++ .../include_c_gen_fn_headers/include_c.v | 16 ++++++++++ 3 files changed, 55 insertions(+) create mode 100644 vlib/v/tests/include_c_gen_fn_headers/cheader.h create mode 100644 vlib/v/tests/include_c_gen_fn_headers/include_c.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 1095acb02..184ae85f6 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -4,6 +4,7 @@ import strings import v.ast import v.util import v.token +import os const print_everything_fns = ['println', 'print', 'eprintln', 'eprint', 'panic'] @@ -1265,6 +1266,35 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. return ast.void_type } } + name := node.get_name() + if name.starts_with('C.') { + println('unknown function ${name}, ' + + 'searching for the C definition in one of the #includes') + mut includes := []string{cap: 5} + for stmt in c.file.stmts { + if stmt is ast.HashStmt { + if stmt.kind == 'include' { + includes << '#include ${stmt.main}' + } + } + } + mut tmp_c_file_with_includes := os.create('tmp.c') or { panic(err) } + tmp_c_file_with_includes.write_string(includes.join('\n')) or { panic(err) } + tmp_c_file_with_includes.close() + + os.execute('v translate fndef ${name[2..]} tmp.c') + x := os.read_file('__cdefs_autogen.v') or { return ast.void_type } + if x.contains('fn ${name}') { + println( + 'function definition for ${name} has been generated in __cdefs_autogen.v. ' + + 'Please re-run the compilation with `v .` or `v run .`') + os.rm('tmp.c') or {} + exit(0) + } else { + println('Failed to generate function definition. Please report it via github.com/vlang/v/issues') + } + os.rm('tmp.c') or {} + } c.error('unknown function: ${node.get_name()}', node.pos) return ast.void_type } diff --git a/vlib/v/tests/include_c_gen_fn_headers/cheader.h b/vlib/v/tests/include_c_gen_fn_headers/cheader.h new file mode 100644 index 000000000..e89cc5a21 --- /dev/null +++ b/vlib/v/tests/include_c_gen_fn_headers/cheader.h @@ -0,0 +1,9 @@ +#include + +void hello_from_c() { + puts("Hello from C!"); +} + +int add_two_numbers(int a, int b) { + return a + b; +} diff --git a/vlib/v/tests/include_c_gen_fn_headers/include_c.v b/vlib/v/tests/include_c_gen_fn_headers/include_c.v new file mode 100644 index 000000000..ae0eac14f --- /dev/null +++ b/vlib/v/tests/include_c_gen_fn_headers/include_c.v @@ -0,0 +1,16 @@ +#flag -I. +#include "cheader.h" + +// fn C.hello_from_c() + +// fn C.add_two_numbers(a int, b int) int + +fn test_include_c_autogen_of_fn_definitions() { + C.hello_from_c() + x := C.add_two_numbers(2, 3) + assert x == 5 +} + +fn main() { + test_include_c_autogen_of_fn_definitions() +} -- 2.39.5