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:
parent
6365d9e070
commit
c14d15bd3d
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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} */')
|
||||
|
@ -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) {
|
||||
|
3
vlib/v/gen/c/testdata/translated/sym.c
vendored
Normal file
3
vlib/v/gen/c/testdata/translated/sym.c
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
int ExternalSymbol(char *hello) {
|
||||
return *hello;
|
||||
}
|
7
vlib/v/gen/c/testdata/translated/translated_module_actual.v
vendored
Normal file
7
vlib/v/gen/c/testdata/translated/translated_module_actual.v
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
[translated]
|
||||
module translated
|
||||
|
||||
#include "@VMODROOT/sym.c"
|
||||
|
||||
[c: 'ExternalSymbol']
|
||||
pub fn external_symbol(&char) int
|
0
vlib/v/gen/c/testdata/translated/v.mod
vendored
Normal file
0
vlib/v/gen/c/testdata/translated/v.mod
vendored
Normal file
2
vlib/v/gen/c/testdata/translated_module.c.must_have
vendored
Normal file
2
vlib/v/gen/c/testdata/translated_module.c.must_have
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
int ExternalSymbol(char* );
|
||||
int a = ExternalSymbol("hello");
|
1
vlib/v/gen/c/testdata/translated_module.out
vendored
Normal file
1
vlib/v/gen/c/testdata/translated_module.out
vendored
Normal file
@ -0,0 +1 @@
|
||||
result: 104
|
9
vlib/v/gen/c/testdata/translated_module.vv
vendored
Normal file
9
vlib/v/gen/c/testdata/translated_module.vv
vendored
Normal 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
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user