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

checker, native: Check arguments of native builtin functions (#15952)

This commit is contained in:
Spydr 2022-10-03 09:41:59 +02:00 committed by GitHub
parent c655847dfb
commit 5b59171a00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 28 deletions

View File

@ -487,6 +487,38 @@ pub fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
return typ
}
pub fn (mut c Checker) builtin_args(mut node ast.CallExpr, fn_name string, func ast.Fn) {
c.inside_println_arg = true
c.expected_type = ast.string_type
node.args[0].typ = c.expr(node.args[0].expr)
arg := node.args[0]
c.check_expr_opt_call(arg.expr, arg.typ)
if arg.typ.is_void() {
c.error('`$fn_name` can not print void expressions', node.pos)
} else if arg.typ == ast.char_type && arg.typ.nr_muls() == 0 {
c.error('`$fn_name` cannot print type `char` directly, print its address or cast it to an integer instead',
node.pos)
}
c.fail_if_unreadable(arg.expr, arg.typ, 'argument to print')
c.inside_println_arg = false
node.return_type = ast.void_type
c.set_node_expected_arg_types(mut node, func)
/*
// TODO: optimize `struct T{} fn (t &T) str() string {return 'abc'} mut a := []&T{} a << &T{} println(a[0])`
// It currently generates:
// `println(T_str_no_ptr(*(*(T**)array_get(a, 0))));`
// ... which works, but could be just:
// `println(T_str(*(T**)array_get(a, 0)));`
prexpr := node.args[0].expr
prtyp := node.args[0].typ
prtyp_sym := c.table.sym(prtyp)
prtyp_is_ptr := prtyp.is_ptr()
prhas_str, prexpects_ptr, prnr_args := prtyp_sym.str_method_info()
eprintln('>>> println hack typ: ${prtyp} | sym.name: ${prtyp_sym.name} | is_ptr: $prtyp_is_ptr | has_str: $prhas_str | expects_ptr: $prexpects_ptr | nr_args: $prnr_args | expr: ${prexpr.str()} ')
*/
}
pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.Type {
fn_name := node.name
if fn_name == 'main' {
@ -713,6 +745,10 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
}
}
if is_native_builtin {
if node.args.len > 0 && fn_name in ['println', 'print', 'eprintln', 'eprint', 'panic'] {
c.builtin_args(mut node, fn_name, func)
return func.return_type
}
return ast.void_type
}
// check for arg (var) of fn type
@ -841,34 +877,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
}
// println / eprintln / panic can print anything
if node.args.len > 0 && fn_name in ['println', 'print', 'eprintln', 'eprint', 'panic'] {
c.inside_println_arg = true
c.expected_type = ast.string_type
node.args[0].typ = c.expr(node.args[0].expr)
arg := node.args[0]
c.check_expr_opt_call(arg.expr, arg.typ)
if arg.typ.is_void() {
c.error('`$fn_name` can not print void expressions', node.pos)
} else if arg.typ == ast.char_type && arg.typ.nr_muls() == 0 {
c.error('`$fn_name` cannot print type `char` directly, print its address or cast it to an integer instead',
node.pos)
}
c.fail_if_unreadable(arg.expr, arg.typ, 'argument to print')
c.inside_println_arg = false
node.return_type = ast.void_type
c.set_node_expected_arg_types(mut node, func)
/*
// TODO: optimize `struct T{} fn (t &T) str() string {return 'abc'} mut a := []&T{} a << &T{} println(a[0])`
// It currently generates:
// `println(T_str_no_ptr(*(*(T**)array_get(a, 0))));`
// ... which works, but could be just:
// `println(T_str(*(T**)array_get(a, 0)));`
prexpr := node.args[0].expr
prtyp := node.args[0].typ
prtyp_sym := c.table.sym(prtyp)
prtyp_is_ptr := prtyp.is_ptr()
prhas_str, prexpects_ptr, prnr_args := prtyp_sym.str_method_info()
eprintln('>>> println hack typ: ${prtyp} | sym.name: ${prtyp_sym.name} | is_ptr: $prtyp_is_ptr | has_str: $prhas_str | expects_ptr: $prexpects_ptr | nr_args: $prnr_args | expr: ${prexpr.str()} ')
*/
c.builtin_args(mut node, fn_name, func)
return func.return_type
}
// `return error(err)` -> `return err`

View File

@ -8,6 +8,14 @@ fn abc() {
println(c)
}
fn abc_direct() {
// print at-exprs directly instead of using variables
println(@LINE)
println(@FILE_LINE)
println(@FN)
}
fn main() {
abc()
abc_direct()
}

View File

@ -1,3 +1,6 @@
3
atexpr.vv:4
abc
13
atexpr.vv:14
abc_direct