mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker,cgen: make boolean field.is_<field> accessible at compile-time as well (#16796)
This commit is contained in:
parent
ad9ca349dc
commit
2ebd3f0cdb
@ -1183,7 +1183,13 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// evaluates comptime field.<name> (from T.fields)
|
||||||
|
if c.check_comptime_is_field_selector(node) {
|
||||||
|
if c.check_comptime_is_field_selector_bool(node) {
|
||||||
|
node.expr_type = ast.bool_type
|
||||||
|
return node.expr_type
|
||||||
|
}
|
||||||
|
}
|
||||||
old_selector_expr := c.inside_selector_expr
|
old_selector_expr := c.inside_selector_expr
|
||||||
c.inside_selector_expr = true
|
c.inside_selector_expr = true
|
||||||
mut typ := c.expr(node.expr)
|
mut typ := c.expr(node.expr)
|
||||||
|
@ -562,6 +562,12 @@ 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 is ast.IntegerLiteral {
|
||||||
// $if method.args.len == 1
|
// $if method.args.len == 1
|
||||||
|
} else if cond.left is ast.SelectorExpr
|
||||||
|
&& c.check_comptime_is_field_selector_bool(cond.left as ast.SelectorExpr) {
|
||||||
|
// field.is_public (from T.fields)
|
||||||
|
} else if cond.right is ast.SelectorExpr
|
||||||
|
&& c.check_comptime_is_field_selector_bool(cond.right as ast.SelectorExpr) {
|
||||||
|
// field.is_public (from T.fields)
|
||||||
} else if cond.left is ast.Ident {
|
} else if cond.left is ast.Ident {
|
||||||
// $if version == 2
|
// $if version == 2
|
||||||
left_type := c.expr(cond.left)
|
left_type := c.expr(cond.left)
|
||||||
@ -716,9 +722,37 @@ fn (mut c Checker) comptime_if_branch(cond ast.Expr, pos token.Pos) ComptimeBran
|
|||||||
}
|
}
|
||||||
return .eval
|
return .eval
|
||||||
}
|
}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
if c.check_comptime_is_field_selector(cond) {
|
||||||
|
if c.check_comptime_is_field_selector_bool(cond) {
|
||||||
|
return .eval
|
||||||
|
}
|
||||||
|
c.error('unknown field `${cond.field_name}` from ${c.comptime_for_field_var}',
|
||||||
|
cond.pos)
|
||||||
|
}
|
||||||
|
return .unknown
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
c.error('invalid `\$if` condition', pos)
|
c.error('invalid `\$if` condition', pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .unknown
|
return .unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (mut c Checker) check_comptime_is_field_selector(node ast.SelectorExpr) bool {
|
||||||
|
if c.inside_comptime_for_field && node.expr is ast.Ident {
|
||||||
|
return (node.expr as ast.Ident).name == c.comptime_for_field_var
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (mut c Checker) check_comptime_is_field_selector_bool(node ast.SelectorExpr) bool {
|
||||||
|
if c.check_comptime_is_field_selector(node) {
|
||||||
|
bool_fields := ['is_mut', 'is_pub', 'is_shared', 'is_atomic', 'is_optional', 'is_array',
|
||||||
|
'is_map', 'is_chan', 'is_struct']
|
||||||
|
return node.field_name in bool_fields
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -17,6 +17,25 @@ fn (mut g Gen) get_comptime_selector_var_type(node ast.ComptimeSelector) (ast.St
|
|||||||
return field, field_name
|
return field, field_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) get_comptime_selector_bool_field(field_name string) bool {
|
||||||
|
field := g.comptime_for_field_value
|
||||||
|
field_typ := g.comptime_for_field_type
|
||||||
|
field_sym := g.table.sym(g.unwrap_generic(g.comptime_for_field_type))
|
||||||
|
|
||||||
|
match field_name {
|
||||||
|
'is_pub' { return field.is_pub }
|
||||||
|
'is_mut' { return field.is_mut }
|
||||||
|
'is_shared' { return field_typ.has_flag(.shared_f) }
|
||||||
|
'is_atomic' { return field_typ.has_flag(.atomic_f) }
|
||||||
|
'is_optional' { return field.typ.has_flag(.optional) }
|
||||||
|
'is_array' { return field_sym.kind in [.array, .array_fixed] }
|
||||||
|
'is_map' { return field_sym.kind == .map }
|
||||||
|
'is_chan' { return field_sym.kind == .chan }
|
||||||
|
'is_struct' { return field_sym.kind == .struct_ }
|
||||||
|
else { return false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
|
fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
if node.left_type.is_ptr() {
|
if node.left_type.is_ptr() {
|
||||||
@ -443,8 +462,15 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) bool {
|
|||||||
}
|
}
|
||||||
.eq, .ne {
|
.eq, .ne {
|
||||||
// TODO Implement `$if method.args.len == 1`
|
// TODO Implement `$if method.args.len == 1`
|
||||||
g.write('1')
|
if cond.left is ast.SelectorExpr || cond.right is ast.SelectorExpr {
|
||||||
return true
|
l := g.comptime_if_cond(cond.left, pkg_exist)
|
||||||
|
g.write(' ${cond.op} ')
|
||||||
|
r := g.comptime_if_cond(cond.right, pkg_exist)
|
||||||
|
return if cond.op == .eq { l == r } else { l != r }
|
||||||
|
} else {
|
||||||
|
g.write('1')
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return true
|
return true
|
||||||
@ -460,6 +486,17 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) bool {
|
|||||||
g.write('${pkg_exist}')
|
g.write('${pkg_exist}')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
if g.inside_comptime_for_field && cond.expr is ast.Ident
|
||||||
|
&& (cond.expr as ast.Ident).name == g.comptime_for_field_var && cond.field_name in ['is_mut', 'is_pub', 'is_shared', 'is_atomic', 'is_optional', 'is_array', 'is_map', 'is_chan', 'is_struct'] {
|
||||||
|
ret_bool := g.get_comptime_selector_bool_field(cond.field_name)
|
||||||
|
g.write(ret_bool.str())
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
g.write('1')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// should be unreachable, but just in case
|
// should be unreachable, but just in case
|
||||||
g.write('1')
|
g.write('1')
|
||||||
|
18
vlib/v/tests/inout/comptime_bool_fields.out
Normal file
18
vlib/v/tests/inout/comptime_bool_fields.out
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
field: a
|
||||||
|
a is mut?: true
|
||||||
|
field: b
|
||||||
|
b is mut?: true
|
||||||
|
b is struct?: true
|
||||||
|
field: c
|
||||||
|
c is pub?: true
|
||||||
|
c is optional?: true
|
||||||
|
field: d
|
||||||
|
d is pub?: true
|
||||||
|
d is map?: true
|
||||||
|
field: e
|
||||||
|
e is pub?: true
|
||||||
|
e is atomic?: true
|
||||||
|
field: f
|
||||||
|
f is pub?: true
|
||||||
|
f is mut?: true
|
||||||
|
f is array?: true
|
51
vlib/v/tests/inout/comptime_bool_fields.vv
Normal file
51
vlib/v/tests/inout/comptime_bool_fields.vv
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
struct Bb {
|
||||||
|
mut:
|
||||||
|
a int
|
||||||
|
b struct {}
|
||||||
|
|
||||||
|
pub:
|
||||||
|
c ?string
|
||||||
|
d map[string]int
|
||||||
|
e atomic int
|
||||||
|
pub mut:
|
||||||
|
f []f64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo[U](val U) {
|
||||||
|
$for field in U.fields {
|
||||||
|
println('field: ${field.name}')
|
||||||
|
|
||||||
|
$if field.is_pub == true {
|
||||||
|
println(field.name + ' is pub?: ${field.is_pub}')
|
||||||
|
}
|
||||||
|
$if field.is_mut {
|
||||||
|
println(field.name + ' is mut?: ${field.is_mut}')
|
||||||
|
}
|
||||||
|
$if field.is_struct {
|
||||||
|
println(field.name + ' is struct?: ${field.is_struct}')
|
||||||
|
}
|
||||||
|
$if field.is_chan {
|
||||||
|
println(field.name + ' is chan?: ${field.is_chan}')
|
||||||
|
}
|
||||||
|
$if field.is_array {
|
||||||
|
println(field.name + ' is array?: ${field.is_array}')
|
||||||
|
}
|
||||||
|
$if field.is_map {
|
||||||
|
println(field.name + ' is map?: ${field.is_map}')
|
||||||
|
}
|
||||||
|
$if field.is_shared {
|
||||||
|
println(field.name + ' is shared?: ${field.is_shared}')
|
||||||
|
}
|
||||||
|
$if field.is_optional {
|
||||||
|
println(field.name + ' is optional?: ${field.is_optional}')
|
||||||
|
}
|
||||||
|
$if field.is_atomic {
|
||||||
|
println(field.name + ' is atomic?: ${field.is_atomic}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
bb := Bb{}
|
||||||
|
foo(bb)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user