mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
parent
73ebf42015
commit
bfc6d5469f
5 changed files with 58 additions and 13 deletions
|
@ -404,8 +404,8 @@ fn (mut vt Vet) const_decl(stmt ast.ConstDecl) {
|
||||||
fn (mut vt Vet) vet_empty_str(expr ast.InfixExpr) {
|
fn (mut vt Vet) vet_empty_str(expr ast.InfixExpr) {
|
||||||
if expr.left is ast.SelectorExpr && expr.right is ast.IntegerLiteral {
|
if expr.left is ast.SelectorExpr && expr.right is ast.IntegerLiteral {
|
||||||
operand := (expr.left as ast.SelectorExpr) // TODO: remove as-casts when multiple conds can be smart-casted.
|
operand := (expr.left as ast.SelectorExpr) // TODO: remove as-casts when multiple conds can be smart-casted.
|
||||||
if operand.expr is ast.Ident && operand.expr.info.typ == ast.string_type_idx
|
if operand.expr is ast.Ident && operand.field_name == 'len'
|
||||||
&& operand.field_name == 'len' {
|
&& operand.expr.info.typ == ast.string_type_idx {
|
||||||
if expr.op != .lt && expr.right.val == '0' {
|
if expr.op != .lt && expr.right.val == '0' {
|
||||||
// Case: `var.len > 0`, `var.len == 0`, `var.len != 0`
|
// Case: `var.len > 0`, `var.len == 0`, `var.len != 0`
|
||||||
op := if expr.op == .gt { '!=' } else { expr.op.str() }
|
op := if expr.op == .gt { '!=' } else { expr.op.str() }
|
||||||
|
|
|
@ -846,10 +846,14 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.eq, .ne {
|
.eq, .ne {
|
||||||
if cond.left is ast.SelectorExpr
|
if mut cond.left is ast.SelectorExpr
|
||||||
&& cond.right in [ast.IntegerLiteral, ast.StringLiteral] {
|
&& cond.right in [ast.IntegerLiteral, ast.StringLiteral] {
|
||||||
// $if field.indirections == 1
|
// $if field.indirections == 1
|
||||||
// $if method.args.len == 1
|
// $if method.args.len == 1
|
||||||
|
if cond.left.typ == 0 && cond.left.name_type == 0
|
||||||
|
&& (cond.left.expr is ast.Ident && cond.left.expr.name.len == 1) {
|
||||||
|
c.expr(mut cond.left)
|
||||||
|
}
|
||||||
return .unknown
|
return .unknown
|
||||||
} else if cond.left is ast.SelectorExpr
|
} else if cond.left is ast.SelectorExpr
|
||||||
&& c.comptime.check_comptime_is_field_selector_bool(cond.left) {
|
&& c.comptime.check_comptime_is_field_selector_bool(cond.left) {
|
||||||
|
@ -908,6 +912,11 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.gt, .lt, .ge, .le {
|
.gt, .lt, .ge, .le {
|
||||||
|
if cond.left is ast.SelectorExpr && cond.left.typ == 0
|
||||||
|
&& cond.left.name_type == 0
|
||||||
|
&& (cond.left.expr is ast.Ident && cond.left.expr.name.len == 1) {
|
||||||
|
c.expr(mut cond.left)
|
||||||
|
}
|
||||||
if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral
|
if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral
|
||||||
&& c.comptime.is_comptime_selector_field_name(cond.left, 'indirections') {
|
&& c.comptime.is_comptime_selector_field_name(cond.left, 'indirections') {
|
||||||
return .unknown
|
return .unknown
|
||||||
|
|
|
@ -612,7 +612,8 @@ 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.comptime_for_field_var.len > 0
|
if cond.left is ast.SelectorExpr && (g.comptime.comptime_for_field_var.len > 0
|
||||||
|| g.comptime.comptime_for_method != unsafe { nil }) {
|
|| g.comptime.comptime_for_method != unsafe { nil }
|
||||||
|
|| cond.left.name_type != 0) {
|
||||||
if cond.right is ast.StringLiteral {
|
if cond.right is ast.StringLiteral {
|
||||||
if cond.left.expr is ast.Ident && cond.left.field_name == 'name' {
|
if cond.left.expr is ast.Ident && cond.left.field_name == 'name' {
|
||||||
if g.comptime.comptime_for_method_var.len > 0
|
if g.comptime.comptime_for_method_var.len > 0
|
||||||
|
@ -645,9 +646,14 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
|
||||||
}
|
}
|
||||||
} else if cond.right is ast.IntegerLiteral {
|
} else if cond.right is ast.IntegerLiteral {
|
||||||
if g.comptime.is_comptime_selector_field_name(cond.left, 'indirections') {
|
if g.comptime.is_comptime_selector_field_name(cond.left, 'indirections') {
|
||||||
|
left_muls := if cond.left.name_type != 0 {
|
||||||
|
g.unwrap_generic(cond.left.name_type).nr_muls()
|
||||||
|
} else {
|
||||||
|
g.comptime.comptime_for_field_type.nr_muls()
|
||||||
|
}
|
||||||
is_true := match cond.op {
|
is_true := match cond.op {
|
||||||
.eq { g.comptime.comptime_for_field_type.nr_muls() == cond.right.val.i64() }
|
.eq { left_muls == cond.right.val.i64() }
|
||||||
.ne { g.comptime.comptime_for_field_type.nr_muls() != cond.right.val.i64() }
|
.ne { left_muls != cond.right.val.i64() }
|
||||||
else { false }
|
else { false }
|
||||||
}
|
}
|
||||||
if is_true {
|
if is_true {
|
||||||
|
@ -723,11 +729,17 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
|
||||||
.gt, .lt, .ge, .le {
|
.gt, .lt, .ge, .le {
|
||||||
if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral
|
if cond.left is ast.SelectorExpr && cond.right is ast.IntegerLiteral
|
||||||
&& g.comptime.is_comptime_selector_field_name(cond.left, 'indirections') {
|
&& g.comptime.is_comptime_selector_field_name(cond.left, 'indirections') {
|
||||||
|
left := cond.left as ast.SelectorExpr
|
||||||
|
left_muls := if left.name_type != 0 {
|
||||||
|
g.unwrap_generic(left.name_type).nr_muls()
|
||||||
|
} else {
|
||||||
|
g.comptime.comptime_for_field_type.nr_muls()
|
||||||
|
}
|
||||||
is_true := match cond.op {
|
is_true := match cond.op {
|
||||||
.gt { g.comptime.comptime_for_field_type.nr_muls() > cond.right.val.i64() }
|
.gt { left_muls > cond.right.val.i64() }
|
||||||
.lt { g.comptime.comptime_for_field_type.nr_muls() < cond.right.val.i64() }
|
.lt { left_muls < cond.right.val.i64() }
|
||||||
.ge { g.comptime.comptime_for_field_type.nr_muls() >= cond.right.val.i64() }
|
.ge { left_muls >= cond.right.val.i64() }
|
||||||
.le { g.comptime.comptime_for_field_type.nr_muls() <= cond.right.val.i64() }
|
.le { left_muls <= cond.right.val.i64() }
|
||||||
else { false }
|
else { false }
|
||||||
}
|
}
|
||||||
if is_true {
|
if is_true {
|
||||||
|
|
23
vlib/v/tests/comptime/comptime_indirections_test.v
Normal file
23
vlib/v/tests/comptime/comptime_indirections_test.v
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
fn count_muls[T](val T) int {
|
||||||
|
mut nr_muls := 0
|
||||||
|
dump(T.indirections)
|
||||||
|
dump(typeof(val).indirections)
|
||||||
|
$if T.indirections > 0 {
|
||||||
|
nr_muls = (int(typeof(val).idx) >> 16) & 0xff
|
||||||
|
}
|
||||||
|
assert nr_muls == T.indirections
|
||||||
|
$if T.indirections != 0 {
|
||||||
|
nr_muls = (int(typeof(val).idx) >> 16) & 0xff
|
||||||
|
}
|
||||||
|
assert nr_muls == T.indirections
|
||||||
|
return nr_muls
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
val := ''
|
||||||
|
pval := &val
|
||||||
|
ppval := &pval
|
||||||
|
assert count_muls(val) == 0
|
||||||
|
assert count_muls(pval) == 1
|
||||||
|
assert count_muls(ppval) == 2
|
||||||
|
}
|
|
@ -177,11 +177,12 @@ pub fn (mut t TypeResolver) get_comptime_selector_type(node ast.ComptimeSelector
|
||||||
return default_type
|
return default_type
|
||||||
}
|
}
|
||||||
|
|
||||||
// is_comptime_selector_field_name checks if the SelectorExpr is related to $for variable accessing specific field name provided by `field_name`
|
// is_comptime_selector_field_name checks if the SelectorExpr is related to $for variable or generic letter accessing specific field name provided by `field_name`
|
||||||
@[inline]
|
@[inline]
|
||||||
pub fn (t &ResolverInfo) is_comptime_selector_field_name(node ast.SelectorExpr, field_name string) bool {
|
pub fn (t &ResolverInfo) is_comptime_selector_field_name(node ast.SelectorExpr, field_name string) bool {
|
||||||
return t.comptime_for_field_var != '' && node.expr is ast.Ident
|
return ((t.comptime_for_field_var != '' && node.expr is ast.Ident
|
||||||
&& node.expr.name == t.comptime_for_field_var && node.field_name == field_name
|
&& node.expr.name == t.comptime_for_field_var) || node.name_type != 0)
|
||||||
|
&& node.field_name == field_name
|
||||||
}
|
}
|
||||||
|
|
||||||
// is_comptime_selector_type checks if the SelectorExpr is related to $for variable accessing .typ field
|
// is_comptime_selector_type checks if the SelectorExpr is related to $for variable accessing .typ field
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue