diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 2382a75dc4..d17fbdeb51 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -211,6 +211,7 @@ pub: is_js bool no_body bool // just a definition `fn C.malloc()` is_builtin bool // this function is defined in builtin/strconv + ctdefine string // has [if myflag] tag pos token.Position } @@ -235,6 +236,7 @@ mut: left_type table.Type // type of `user` receiver_type table.Type // User return_type table.Type + should_be_skipped bool } pub struct CallArg { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 09b6b92ffb..f1239c9f39 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -120,6 +120,11 @@ fn (c mut Checker) check_file_in_main(file ast.File) bool { c.warn('function `$it.name` $no_pub_in_main_warning', it.pos) } } + if it.ctdefine.len > 0 { + if it.return_type != table.void_type { + c.error('only functions that do NOT return values can have `[if ${it.ctdefine}]` tags', it.pos) + } + } } ast.StructDecl { if it.is_pub { @@ -497,6 +502,9 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type { //println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod') c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos) } + if method.return_type == table.void_type && method.ctdefine.len > 0 && method.ctdefine !in c.pref.compile_defines { + call_expr.should_be_skipped = true + } nr_args := if method.args.len == 0 { 0 } else {method.args.len - 1} min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 } if call_expr.args.len < min_required_args { @@ -612,6 +620,11 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type { return table.void_type } call_expr.return_type = f.return_type + + if f.return_type == table.void_type && f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines { + call_expr.should_be_skipped = true + } + if f.is_c || call_expr.is_c || f.is_js || call_expr.is_js { for arg in call_expr.args { c.expr(arg.expr) diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 4dfc9fbc0c..f66bc790f4 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -224,6 +224,9 @@ fn (mut g Gen) fn_args(args []table.Arg, is_variadic bool) { } fn (mut g Gen) call_expr(node ast.CallExpr) { + if node.should_be_skipped { + return + } gen_or := !g.is_assign_rhs && node.or_block.stmts.len > 0 tmp_opt := if gen_or { g.new_tmp_var() } else { '' } if gen_or { diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 14811b497f..3108ab49f2 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -170,6 +170,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { end_pos = p.tok.position() return_type = p.parse_type() } + ctdefine := p.attr_ctdefine // Register if is_method { mut type_sym := p.table.get_type_symbol(rec_type) @@ -181,6 +182,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { is_variadic: is_variadic is_generic: is_generic is_pub: is_pub + ctdefine: ctdefine }) } else { if is_c { @@ -202,6 +204,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { is_js: is_js is_generic: is_generic is_pub: is_pub + ctdefine: ctdefine }) } // Body @@ -212,6 +215,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { } p.close_scope() p.attr = '' + p.attr_ctdefine = '' return ast.FnDecl{ name: name stmts: stmts @@ -231,6 +235,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { no_body: no_body pos: start_pos.extend(end_pos) is_builtin: p.builtin_mod || p.mod in util.builtin_module_parts + ctdefine: ctdefine } } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 3b5e3135bf..03d315fb7d 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -31,6 +31,7 @@ mut: builtin_mod bool // are we in the `builtin` module? mod string // current module name attr string + attr_ctdefine string expr_mod string scope &ast.Scope global_scope &ast.Scope @@ -490,8 +491,10 @@ pub fn (mut p Parser) stmt() ast.Stmt { fn (mut p Parser) attribute() ast.Attr { p.check(.lsbr) + mut is_if_attr := false if p.tok.kind == .key_if { p.next() + is_if_attr = true } mut name := p.check_name() if p.tok.kind == .colon { @@ -505,6 +508,9 @@ fn (mut p Parser) attribute() ast.Attr { } p.check(.rsbr) p.attr = name + if is_if_attr { + p.attr_ctdefine = name + } return ast.Attr{ name: name } diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 13911885b4..4308489231 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -27,6 +27,7 @@ pub: is_generic bool is_pub bool mod string + ctdefine string // compile time define. myflag, when [if myflag] tag } pub struct Arg {