1
0
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:
Felipe Pena 2023-01-10 14:45:06 -03:00 committed by GitHub
parent cf95d77584
commit 09f48455c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 2 deletions

View File

@ -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) {

View File

@ -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 {}`

View File

@ -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 {

View 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'
}