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 {
|
.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
|
// $if method.args.len == 1
|
||||||
} else if cond.left is ast.SelectorExpr
|
} else if cond.left is ast.SelectorExpr
|
||||||
&& c.check_comptime_is_field_selector_bool(cond.left as ast.SelectorExpr) {
|
&& c.check_comptime_is_field_selector_bool(cond.left as ast.SelectorExpr) {
|
||||||
|
@ -193,6 +193,7 @@ mut:
|
|||||||
// nr_vars_to_free int
|
// nr_vars_to_free int
|
||||||
// doing_autofree_tmp bool
|
// doing_autofree_tmp bool
|
||||||
comptime_for_method string // $for method in T.methods {}
|
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_var string // $for field in T.fields {}; the variable name
|
||||||
comptime_for_field_value ast.StructField // value of the field variable
|
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 {}`
|
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 {
|
.eq, .ne {
|
||||||
// TODO Implement `$if method.args.len == 1`
|
// 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 {
|
if cond.left is ast.SelectorExpr || cond.right is ast.SelectorExpr {
|
||||||
l, d1 := g.comptime_if_cond(cond.left, pkg_exist)
|
l, d1 := g.comptime_if_cond(cond.left, pkg_exist)
|
||||||
g.write(' ${cond.op} ')
|
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 {
|
struct CurrentComptimeValues {
|
||||||
inside_comptime_for_field bool
|
inside_comptime_for_field bool
|
||||||
comptime_for_method string
|
comptime_for_method string
|
||||||
|
comptime_for_method_var string
|
||||||
comptime_for_field_var string
|
comptime_for_field_var string
|
||||||
comptime_for_field_value ast.StructField
|
comptime_for_field_value ast.StructField
|
||||||
comptime_for_field_type ast.Type
|
comptime_for_field_type ast.Type
|
||||||
@ -601,13 +616,14 @@ struct CurrentComptimeValues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) push_existing_comptime_values() {
|
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() {
|
fn (mut g Gen) pop_existing_comptime_values() {
|
||||||
old := g.comptime_values_stack.pop()
|
old := g.comptime_values_stack.pop()
|
||||||
g.inside_comptime_for_field = old.inside_comptime_for_field
|
g.inside_comptime_for_field = old.inside_comptime_for_field
|
||||||
g.comptime_for_method = old.comptime_for_method
|
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_var = old.comptime_for_field_var
|
||||||
g.comptime_for_field_value = old.comptime_for_field_value
|
g.comptime_for_field_value = old.comptime_for_field_value
|
||||||
g.comptime_for_field_type = old.comptime_for_field_type
|
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 = method.name
|
||||||
|
g.comptime_for_method_var = node.val_var
|
||||||
g.writeln('/* method ${i} */ {')
|
g.writeln('/* method ${i} */ {')
|
||||||
g.writeln('\t${node.val_var}.name = _SLIT("${method.name}");')
|
g.writeln('\t${node.val_var}.name = _SLIT("${method.name}");')
|
||||||
if method.attrs.len == 0 {
|
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