diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index c749cfa976..c43073a3c9 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -561,7 +561,9 @@ fn (mut c Checker) comptime_if_branch(cond ast.Expr, pos token.Pos) ComptimeBran } } .eq, .ne { - if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral { + if cond.left is ast.SelectorExpr + && cond.right in [ast.IntegerLiteral, ast.StringLiteral] { + return .unknown // $if method.args.len == 1 } else if cond.left is ast.SelectorExpr && c.check_comptime_is_field_selector_bool(cond.left as ast.SelectorExpr) { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index a6732f99dc..623c85c63d 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -193,6 +193,7 @@ mut: // nr_vars_to_free int // doing_autofree_tmp bool comptime_for_method string // $for method in T.methods {} + comptime_for_method_var string // $for method in T.methods {}; the variable name comptime_for_field_var string // $for field in T.fields {}; the variable name comptime_for_field_value ast.StructField // value of the field variable comptime_for_field_type ast.Type // type of the field variable inferred from `$if field.typ is T {}` diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index d2558e4a48..9a51190d05 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -496,6 +496,20 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) { } .eq, .ne { // TODO Implement `$if method.args.len == 1` + if cond.left is ast.SelectorExpr && g.comptime_for_method.len > 0 + && cond.right is ast.StringLiteral { + selector := cond.left as ast.SelectorExpr + if selector.expr is ast.Ident + && (selector.expr as ast.Ident).name == g.comptime_for_method_var && selector.field_name == 'name' { + is_equal := g.comptime_for_method == cond.right.val + if is_equal { + g.write('1') + } else { + g.write('0') + } + return is_equal, true + } + } if cond.left is ast.SelectorExpr || cond.right is ast.SelectorExpr { l, d1 := g.comptime_if_cond(cond.left, pkg_exist) g.write(' ${cond.op} ') @@ -594,6 +608,7 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) { struct CurrentComptimeValues { inside_comptime_for_field bool comptime_for_method string + comptime_for_method_var string comptime_for_field_var string comptime_for_field_value ast.StructField comptime_for_field_type ast.Type @@ -601,13 +616,14 @@ struct CurrentComptimeValues { } fn (mut g Gen) push_existing_comptime_values() { - g.comptime_values_stack << CurrentComptimeValues{g.inside_comptime_for_field, g.comptime_for_method, g.comptime_for_field_var, g.comptime_for_field_value, g.comptime_for_field_type, g.comptime_var_type_map.clone()} + g.comptime_values_stack << CurrentComptimeValues{g.inside_comptime_for_field, g.comptime_for_method, g.comptime_for_method_var, g.comptime_for_field_var, g.comptime_for_field_value, g.comptime_for_field_type, g.comptime_var_type_map.clone()} } fn (mut g Gen) pop_existing_comptime_values() { old := g.comptime_values_stack.pop() g.inside_comptime_for_field = old.inside_comptime_for_field g.comptime_for_method = old.comptime_for_method + g.comptime_for_method_var = old.comptime_for_method_var g.comptime_for_field_var = old.comptime_for_field_var g.comptime_for_field_value = old.comptime_for_field_value g.comptime_for_field_type = old.comptime_for_field_type @@ -647,6 +663,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { } } g.comptime_for_method = method.name + g.comptime_for_method_var = node.val_var g.writeln('/* method ${i} */ {') g.writeln('\t${node.val_var}.name = _SLIT("${method.name}");') if method.attrs.len == 0 { diff --git a/vlib/v/tests/comptime_method_call_with_check_test.v b/vlib/v/tests/comptime_method_call_with_check_test.v new file mode 100644 index 0000000000..d0ca5a97fe --- /dev/null +++ b/vlib/v/tests/comptime_method_call_with_check_test.v @@ -0,0 +1,26 @@ +struct TestStruct {} + +fn (t TestStruct) one_arg(a string) string { + println(a) + return a +} + +fn (t TestStruct) two_args(a string, b int) string { + println('${a}:${b}') + return a +} + +fn test_main() { + t := TestStruct{} + mut out := '' + $for method in TestStruct.methods { + $if method.name == 'one_arg' { + res := t.$method(method.name) + out += res + } $else $if method.name == 'two_args' { + res := t.$method(method.name, 42) + out += res + } + } + assert out == 'one_argtwo_args' +}