all: support overriding individual function from .v files in .c.v or .js.v files.

pull/11270/head
Delyan Angelov 2021-08-22 13:49:11 +03:00
parent ed06c47a51
commit ec196cfcd1
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
11 changed files with 81 additions and 5 deletions

View File

@ -388,7 +388,8 @@ pub:
method_idx int
rec_mut bool // is receiver mutable
rec_share ShareType
language Language
language Language // V, C, JS
file_mode Language // whether *the file*, where a function was a '.c.v', '.js.v' etc.
no_body bool // just a definition `fn C.malloc()`
is_builtin bool // this function is defined in builtin/strconv
body_pos token.Position // function bodys position

View File

@ -87,6 +87,7 @@ pub:
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
no_body bool // a pure declaration like `fn abc(x int)`; used in .vh files, C./JS. fns.
mod string
file_mode Language
pos token.Position
return_type_pos token.Position
pub mut:

View File

@ -364,6 +364,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
&& (p.file_base.ends_with('_test.v')
|| p.file_base.all_before_last('.v').all_before_last('.').ends_with('_test'))
file_mode := p.file_backend_mode
// Register
if is_method {
mut type_sym := p.table.get_type_symbol(rec.typ)
@ -386,6 +387,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
}
type_sym_method_idx = type_sym.register_method(ast.Fn{
name: name
file_mode: file_mode
params: params
return_type: return_type
is_variadic: is_variadic
@ -412,11 +414,21 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
} else {
name = p.prepend_mod(name)
}
if !p.pref.translated && language == .v && name in p.table.fns {
if !p.pref.translated && language == .v {
if existing := p.table.fns[name] {
if existing.name != '' {
if file_mode == .v && existing.file_mode != .v {
// a definition made in a .c.v file, should have a priority over a .v file definition of the same function
name = p.prepend_mod('pure_v_but_overriden_by_${existing.file_mode}_$short_fn_name')
} else {
p.table.redefined_fns << name
}
}
}
}
p.table.register_fn(ast.Fn{
name: name
file_mode: file_mode
params: params
return_type: return_type
is_variadic: is_variadic

View File

@ -0,0 +1,3 @@
main
mod1/c/implementation.o
main_test

View File

@ -0,0 +1,4 @@
Do not delete this file.
It is used by V to stop the lookup for v.mod,
so that the top level vlib/v.mod is not found,
if you delete mod1/v.mod .

View File

@ -0,0 +1,15 @@
module main
import v.tests.project_with_c_code_3.mod1
fn main() {
res := mod1.vadd(1, 2)
println('mod1.vadd(1, 2): ' + res.str())
$if js {
assert res == 2003
} $else {
assert res == 1003
}
println('mod1.a_common_pure_v_fn(): ' + mod1.a_common_pure_v_fn().str())
assert mod1.a_common_pure_v_fn() == 987654
}

View File

@ -0,0 +1,13 @@
import v.tests.project_with_c_code_3.mod1
fn test_using_c_code_in_the_same_module_works() {
$if js {
assert 2003 == mod1.vadd(1, 2)
} $else {
assert 1003 == mod1.vadd(1, 2)
}
}
fn test_a_common_pure_v_fn_works() {
assert mod1.a_common_pure_v_fn() == 987654
}

View File

@ -0,0 +1,5 @@
Module {
name: 'mod1',
description: 'A simple module, containing C code.',
dependencies: []
}

View File

@ -0,0 +1,5 @@
module mod1
pub fn vadd(a int, b int) int {
return 1003
}

View File

@ -0,0 +1,6 @@
module mod1
// NB: the function here, overrides the one from wrapper.v
pub fn vadd(a int, b int) int {
return 2003
}

View File

@ -0,0 +1,11 @@
module mod1
// NB: the function here, should be overriden by the one in the wrapper.c.v file with the same name
pub fn vadd(a int, b int) int {
return 123456
}
// this should NOT be overriden by the different wrapper.X.v files:
pub fn a_common_pure_v_fn() int {
return 987654
}