1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ast,checker,parser,cgen: [c:'sym'] rework; allow compiling code from .v files tagged with [translated] without needing -translated too (#17125)

This commit is contained in:
l-m 2023-01-26 15:47:38 +00:00 committed by GitHub
parent 6365d9e070
commit c14d15bd3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 87 additions and 58 deletions

View File

@ -513,39 +513,40 @@ pub mut:
[minify]
pub struct FnDecl {
pub:
name string // 'math.bits.normalize'
short_name string // 'normalize'
mod string // 'math.bits'
is_deprecated bool
is_pub bool
is_variadic bool
is_anon bool
is_noreturn bool // true, when [noreturn] is used on a fn
is_manualfree bool // true, when [manualfree] is used on a fn
is_main bool // true for `fn main()`
is_test bool // true for `fn test_abcde() {}`, false for `fn test_abc(x int) {}`, or for fns that do not start with test_
is_conditional bool // true for `[if abc] fn abc(){}`
is_exported bool // true for `[export: 'exact_C_name']`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
is_unsafe bool // true, when [unsafe] is used on a fn
is_markused bool // true, when an explict `[markused]` tag was put on a fn; `-skip-unused` will not remove that fn
receiver StructField // TODO this is not a struct field
receiver_pos token.Pos // `(u User)` in `fn (u User) name()` position
is_method bool
method_type_pos token.Pos // `User` in ` fn (u User)` position
method_idx int
rec_mut bool // is receiver mutable
rec_share ShareType
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.Pos // function bodys position
file string
generic_names []string
is_direct_arr bool // direct array access
attrs []Attr
ctdefine_idx int = -1 // the index in fn.attrs of `[if xyz]`, when such attribute exists
name string // 'math.bits.normalize'
short_name string // 'normalize'
mod string // 'math.bits'
is_deprecated bool
is_pub bool
is_variadic bool
is_anon bool
is_noreturn bool // true, when [noreturn] is used on a fn
is_manualfree bool // true, when [manualfree] is used on a fn
is_main bool // true for `fn main()`
is_test bool // true for `fn test_abcde() {}`, false for `fn test_abc(x int) {}`, or for fns that do not start with test_
is_conditional bool // true for `[if abc] fn abc(){}`
is_exported bool // true for `[export: 'exact_C_name']`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
is_unsafe bool // true, when [unsafe] is used on a fn
is_markused bool // true, when an explict `[markused]` tag was put on a fn; `-skip-unused` will not remove that fn
is_file_translated bool // true, when the file it resides in is `[translated]`
receiver StructField // TODO this is not a struct field
receiver_pos token.Pos // `(u User)` in `fn (u User) name()` position
is_method bool
method_type_pos token.Pos // `User` in ` fn (u User)` position
method_idx int
rec_mut bool // is receiver mutable
rec_share ShareType
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.Pos // function bodys position
file string
generic_names []string
is_direct_arr bool // direct array access
attrs []Attr
ctdefine_idx int = -1 // the index in fn.attrs of `[if xyz]`, when such attribute exists
pub mut:
idx int // index in an external container; can be used to refer to the function in a more efficient way, just by its integer index
params []Param
@ -593,6 +594,7 @@ pub mut:
is_keep_alive bool // GC must not free arguments before fn returns
is_noreturn bool // whether the function/method is marked as [noreturn]
is_ctor_new bool // if JS ctor calls requires `new` before call, marked as `[use_new]` in V
is_file_translated bool // true, when the file it resides in is `[translated]`
args []CallArg
expected_arg_types []Type
comptime_ret_val bool

View File

@ -93,24 +93,25 @@ pub fn (t &Table) panic(message string) {
[minify]
pub struct Fn {
pub:
is_variadic bool
language Language
is_pub bool
is_ctor_new bool // `[use_new] fn JS.Array.prototype.constructor()`
is_deprecated bool // `[deprecated] fn abc(){}`
is_noreturn bool // `[noreturn] fn abc(){}`
is_unsafe bool // `[unsafe] fn abc(){}`
is_placeholder bool
is_main bool // `fn main(){}`
is_test bool // `fn test_abc(){}`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
is_method bool // true for `fn (x T) name()`, and for interface declarations (which are also for methods)
no_body bool // a pure declaration like `fn abc(x int)`; used in .vh files, C./JS. fns.
mod string
file string
file_mode Language
pos token.Pos
return_type_pos token.Pos
is_variadic bool
language Language
is_pub bool
is_ctor_new bool // `[use_new] fn JS.Array.prototype.constructor()`
is_deprecated bool // `[deprecated] fn abc(){}`
is_noreturn bool // `[noreturn] fn abc(){}`
is_unsafe bool // `[unsafe] fn abc(){}`
is_placeholder bool
is_main bool // `fn main(){}`
is_test bool // `fn test_abc(){}`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
is_method bool // true for `fn (x T) name()`, and for interface declarations (which are also for methods)
no_body bool // a pure declaration like `fn abc(x int)`; used in .vh files, C./JS. fns.
is_file_translated bool // true, when the file it resides in is `[translated]`
mod string
file string
file_mode Language
pos token.Pos
return_type_pos token.Pos
pub mut:
return_type Type
receiver_type Type // != 0, when .is_method == true

View File

@ -887,6 +887,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
return ast.void_type
}
node.is_file_translated = func.is_file_translated
node.is_noreturn = func.is_noreturn
node.is_ctor_new = func.is_ctor_new
if !found_in_args {
@ -909,7 +910,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
}
node.is_keep_alive = func.is_keep_alive
if func.language == .v && func.no_body && !c.pref.translated && !c.file.is_translated
&& !func.is_unsafe && func.mod != 'builtin' {
&& !func.is_unsafe && !func.is_file_translated && func.mod != 'builtin' {
c.error('cannot call a function that does not have a body', node.pos)
}
if node.concrete_types.len > 0 && func.generic_names.len > 0

View File

@ -4357,15 +4357,16 @@ fn (mut g Gen) ident(node ast.Ident) {
}
}
} else if node.info is ast.IdentFn {
if g.pref.translated || g.file.is_translated {
// `p_mobjthinker` => `P_MobjThinker`
if func := g.table.find_fn(node.name) {
// TODO PERF fn lookup for each fn call in translated mode
// TODO PERF fn lookup for each fn call in translated mode
if func := g.table.find_fn(node.name) {
if g.pref.translated || g.file.is_translated || func.is_file_translated {
// `p_mobjthinker` => `P_MobjThinker`
if cattr := func.attrs.find_first('c') {
name = cattr.arg
}
}
}
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__') {
key := node.name
g.write('/* obf identfn: ${key} */')

View File

@ -446,7 +446,7 @@ fn (mut g Gen) c_fn_name(node &ast.FnDecl) !string {
name = g.generic_fn_name(g.cur_concrete_types, name)
}
if g.pref.translated || g.file.is_translated {
if g.pref.translated || g.file.is_translated || node.is_file_translated {
if cattr := node.attrs.find_first('c') {
// This fixes unknown symbols errors when building separate .c => .v files into .o files
// example:
@ -1362,7 +1362,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
} else {
name = c_name(name)
}
if g.pref.translated || g.file.is_translated {
if g.pref.translated || g.file.is_translated || node.is_file_translated {
// For `[c: 'P_TryMove'] fn p_trymove( ... `
// every time `p_trymove` is called, `P_TryMove` must be generated instead.
if f := g.table.find_fn(node.name) {

View File

@ -0,0 +1,3 @@
int ExternalSymbol(char *hello) {
return *hello;
}

View File

@ -0,0 +1,7 @@
[translated]
module translated
#include "@VMODROOT/sym.c"
[c: 'ExternalSymbol']
pub fn external_symbol(&char) int

View File

View File

@ -0,0 +1,2 @@
int ExternalSymbol(char* );
int a = ExternalSymbol("hello");

View File

@ -0,0 +1 @@
result: 104

View File

@ -0,0 +1,9 @@
module main
import v.gen.c.testdata.translated { external_symbol }
fn main() {
a := external_symbol(c'hello')
println('result: ${a}')
assert a == 104
}

View File

@ -495,6 +495,7 @@ run them via `v file.v` instead',
is_test: is_test
is_keep_alive: is_keep_alive
is_method: false
is_file_translated: p.is_translated
//
attrs: p.attrs
is_conditional: conditional_ctdefine_idx != ast.invalid_type_idx
@ -550,6 +551,7 @@ run them via `v file.v` instead',
is_keep_alive: is_keep_alive
is_unsafe: is_unsafe
is_markused: is_markused
is_file_translated: p.is_translated
//
attrs: p.attrs
is_conditional: conditional_ctdefine_idx != ast.invalid_type_idx