mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker,cgen: allow method.name checking in comptime (#16931)
This commit is contained in:
parent
cf95d77584
commit
09f48455c5
@ -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) {
|
||||
|
@ -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 {}`
|
||||
|
@ -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 {
|
||||
|
26
vlib/v/tests/comptime_method_call_with_check_test.v
Normal file
26
vlib/v/tests/comptime_method_call_with_check_test.v
Normal file
@ -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'
|
||||
}
|
Loading…
Reference in New Issue
Block a user