mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker, cgen: make comptime field.indirections working with logical operators (#17990)
This commit is contained in:
parent
59d91e0514
commit
c339ea2ce2
@ -655,6 +655,19 @@ fn (mut c Checker) comptime_if_branch(cond ast.Expr, pos token.Pos) ComptimeBran
|
||||
.eq, .ne {
|
||||
if cond.left is ast.SelectorExpr
|
||||
&& cond.right in [ast.IntegerLiteral, ast.StringLiteral] {
|
||||
if cond.right is ast.IntegerLiteral
|
||||
&& c.is_comptime_selector_field_name(cond.left as ast.SelectorExpr, 'indirections') {
|
||||
ret := match cond.op {
|
||||
.eq { c.comptime_fields_default_type.nr_muls() == cond.right.val.i64() }
|
||||
.ne { c.comptime_fields_default_type.nr_muls() != cond.right.val.i64() }
|
||||
else { false }
|
||||
}
|
||||
return if ret {
|
||||
ComptimeBranchSkipState.eval
|
||||
} else {
|
||||
ComptimeBranchSkipState.skip
|
||||
}
|
||||
}
|
||||
return .unknown
|
||||
// $if method.args.len == 1
|
||||
} else if cond.left is ast.SelectorExpr
|
||||
@ -711,6 +724,27 @@ fn (mut c Checker) comptime_if_branch(cond ast.Expr, pos token.Pos) ComptimeBran
|
||||
c.error('invalid `\$if` condition', cond.pos)
|
||||
}
|
||||
}
|
||||
.gt, .lt, .ge, .le {
|
||||
if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral {
|
||||
if c.is_comptime_selector_field_name(cond.left as ast.SelectorExpr,
|
||||
'indirections')
|
||||
{
|
||||
ret := match cond.op {
|
||||
.gt { c.comptime_fields_default_type.nr_muls() > cond.right.val.i64() }
|
||||
.lt { c.comptime_fields_default_type.nr_muls() < cond.right.val.i64() }
|
||||
.ge { c.comptime_fields_default_type.nr_muls() >= cond.right.val.i64() }
|
||||
.le { c.comptime_fields_default_type.nr_muls() <= cond.right.val.i64() }
|
||||
else { false }
|
||||
}
|
||||
return if ret {
|
||||
ComptimeBranchSkipState.eval
|
||||
} else {
|
||||
ComptimeBranchSkipState.skip
|
||||
}
|
||||
}
|
||||
}
|
||||
c.error('invalid `\$if` condition', cond.pos)
|
||||
}
|
||||
else {
|
||||
c.error('invalid `\$if` condition', cond.pos)
|
||||
}
|
||||
@ -858,7 +892,14 @@ fn (mut c Checker) get_comptime_selector_type(node ast.ComptimeSelector, default
|
||||
return default_type
|
||||
}
|
||||
|
||||
// check_comptime_is_field_selector checks if the SelectorExpr is related to $for variable accessing .typ field
|
||||
// is_comptime_selector_field_name checks if the SelectorExpr is related to $for variable accessing specific field name provided by `field_name`
|
||||
[inline]
|
||||
fn (mut c Checker) is_comptime_selector_field_name(node ast.SelectorExpr, field_name string) bool {
|
||||
return c.inside_comptime_for_field && node.expr is ast.Ident
|
||||
&& (node.expr as ast.Ident).name == c.comptime_for_field_var && node.field_name == field_name
|
||||
}
|
||||
|
||||
// is_comptime_selector_type checks if the SelectorExpr is related to $for variable accessing .typ field
|
||||
[inline]
|
||||
fn (mut c Checker) is_comptime_selector_type(node ast.SelectorExpr) bool {
|
||||
if c.inside_comptime_for_field && node.expr is ast.Ident {
|
||||
|
@ -537,28 +537,43 @@ 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_field_var.len > 0 || g.comptime_for_method.len > 0)
|
||||
&& cond.right is ast.StringLiteral {
|
||||
selector := cond.left as ast.SelectorExpr
|
||||
if selector.expr is ast.Ident && selector.field_name == 'name' {
|
||||
if g.comptime_for_method_var.len > 0
|
||||
&& (selector.expr as ast.Ident).name == g.comptime_for_method_var {
|
||||
is_equal := g.comptime_for_method == cond.right.val
|
||||
if is_equal {
|
||||
&& (g.comptime_for_field_var.len > 0 || g.comptime_for_method.len > 0) {
|
||||
if cond.right is ast.StringLiteral {
|
||||
selector := cond.left as ast.SelectorExpr
|
||||
if selector.expr is ast.Ident && selector.field_name == 'name' {
|
||||
if g.comptime_for_method_var.len > 0
|
||||
&& (selector.expr as ast.Ident).name == g.comptime_for_method_var {
|
||||
is_equal := g.comptime_for_method == cond.right.val
|
||||
if is_equal {
|
||||
g.write('1')
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
return is_equal, true
|
||||
} else if g.comptime_for_field_var.len > 0
|
||||
&& (selector.expr as ast.Ident).name == g.comptime_for_field_var {
|
||||
is_equal := g.comptime_for_field_value.name == cond.right.val
|
||||
if is_equal {
|
||||
g.write('1')
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
return is_equal, true
|
||||
}
|
||||
}
|
||||
} else if cond.right is ast.IntegerLiteral {
|
||||
if g.is_comptime_selector_field_name(cond.left, 'indirections') {
|
||||
is_true := match cond.op {
|
||||
.eq { g.comptime_for_field_type.nr_muls() == cond.right.val.i64() }
|
||||
.ne { g.comptime_for_field_type.nr_muls() != cond.right.val.i64() }
|
||||
else { false }
|
||||
}
|
||||
if is_true {
|
||||
g.write('1')
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
return is_equal, true
|
||||
} else if g.comptime_for_field_var.len > 0
|
||||
&& (selector.expr as ast.Ident).name == g.comptime_for_field_var {
|
||||
is_equal := g.comptime_for_field_value.name == cond.right.val
|
||||
if is_equal {
|
||||
g.write('1')
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
return is_equal, true
|
||||
return is_true, true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -611,6 +626,30 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
|
||||
return true, true
|
||||
}
|
||||
}
|
||||
.gt, .lt, .ge, .le {
|
||||
if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral {
|
||||
if g.is_comptime_selector_field_name(cond.left as ast.SelectorExpr,
|
||||
'indirections')
|
||||
{
|
||||
is_true := match cond.op {
|
||||
.gt { g.comptime_for_field_type.nr_muls() > cond.right.val.i64() }
|
||||
.lt { g.comptime_for_field_type.nr_muls() < cond.right.val.i64() }
|
||||
.ge { g.comptime_for_field_type.nr_muls() >= cond.right.val.i64() }
|
||||
.le { g.comptime_for_field_type.nr_muls() <= cond.right.val.i64() }
|
||||
else { false }
|
||||
}
|
||||
if is_true {
|
||||
g.write('1')
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
return is_true, true
|
||||
} else {
|
||||
return true, false
|
||||
}
|
||||
}
|
||||
return true, false
|
||||
}
|
||||
else {
|
||||
return true, false
|
||||
}
|
||||
@ -679,6 +718,13 @@ fn (mut g Gen) pop_existing_comptime_values() {
|
||||
g.comptime_var_type_map = old.comptime_var_type_map.clone()
|
||||
}
|
||||
|
||||
// is_comptime_selector_field_name checks if the SelectorExpr is related to $for variable accessing specific field name provided by `field_name`
|
||||
[inline]
|
||||
fn (mut g Gen) is_comptime_selector_field_name(node ast.SelectorExpr, field_name string) bool {
|
||||
return g.inside_comptime_for_field && node.expr is ast.Ident
|
||||
&& (node.expr as ast.Ident).name == g.comptime_for_field_var && node.field_name == field_name
|
||||
}
|
||||
|
||||
// check_comptime_is_field_selector checks if the SelectorExpr is related to $for variable accessing .typ field
|
||||
[inline]
|
||||
fn (mut g Gen) is_comptime_selector_type(node ast.SelectorExpr) bool {
|
||||
|
32
vlib/v/tests/comptime_field_indirections_test.v
Normal file
32
vlib/v/tests/comptime_field_indirections_test.v
Normal file
@ -0,0 +1,32 @@
|
||||
struct Encoder {}
|
||||
|
||||
struct Writer {}
|
||||
|
||||
struct StructType[T] {
|
||||
mut:
|
||||
val &T
|
||||
val2 T
|
||||
}
|
||||
|
||||
fn (e &Encoder) encode_struct[U](val U, mut wr Writer) ! {
|
||||
$for field in U.fields {
|
||||
if field.indirections == 1 {
|
||||
assert field.indirections == 1
|
||||
value := val.$(field.name)
|
||||
$if field.indirections == 1 {
|
||||
assert *value == 'ads'
|
||||
} $else {
|
||||
assert false
|
||||
}
|
||||
} else {
|
||||
assert field.name == 'val2'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_indirection_checking() {
|
||||
e := Encoder{}
|
||||
mut sb := Writer{}
|
||||
mut string_pointer := 'ads'
|
||||
e.encode_struct(StructType[string]{ val: &string_pointer }, mut sb)!
|
||||
}
|
Loading…
Reference in New Issue
Block a user