Skip to content

Commit

Permalink
checker,cgen: allow method.name checking in comptime (#16931)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Jan 10, 2023
1 parent cf95d77 commit 09f4845
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 2 deletions.
4 changes: 3 additions & 1 deletion vlib/v/checker/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}`
Expand Down
19 changes: 18 additions & 1 deletion vlib/v/gen/c/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -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} ')
Expand Down Expand Up @@ -594,20 +608,22 @@ 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
comptime_var_type_map map[string]ast.Type
}

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
Expand Down Expand Up @@ -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 {
Expand Down
26 changes: 26 additions & 0 deletions vlib/v/tests/comptime_method_call_with_check_test.v
Original file line number Diff line number Diff line change
@@ -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'
}

0 comments on commit 09f4845

Please sign in to comment.