mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
eval: add more infix op support; fix early func return (#24965)
This commit is contained in:
parent
a309593f56
commit
af046e1c6e
@ -64,6 +64,7 @@ pub mut:
|
||||
scope_idx int // this is increased when e.open_scope() is called, decreased when e.close_scope() (and all variables with that scope level deleted)
|
||||
returning bool
|
||||
return_values []Object
|
||||
executed_return_stmt bool // already executed a return stmt in func
|
||||
cur_mod string
|
||||
cur_file string
|
||||
|
||||
@ -152,6 +153,7 @@ pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) {
|
||||
scope_idx: e.scope_idx
|
||||
}
|
||||
}
|
||||
e.executed_return_stmt = false
|
||||
e.stmts(func.stmts)
|
||||
e.returning = false
|
||||
e.close_scope()
|
||||
@ -317,6 +319,11 @@ pub fn (mut e Eval) comptime_cond(cond ast.Expr) bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.InfixExpr {
|
||||
left := e.comptime_cond(cond.left)
|
||||
right := e.comptime_cond(cond.right)
|
||||
return e.infix_expr(left, right, cond.op, ast.bool_type) as bool
|
||||
}
|
||||
else {
|
||||
e.error('unsupported expression')
|
||||
}
|
||||
|
@ -498,6 +498,9 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
match expr.op {
|
||||
.not {
|
||||
return !(e.expr(expr.right, ast.bool_type) as bool)
|
||||
}
|
||||
.amp {
|
||||
x := e.expr(expr.right, expr.right_type)
|
||||
return Ptr{
|
||||
|
@ -6,6 +6,18 @@ import v.ast
|
||||
|
||||
fn (e &Eval) infix_expr(left Object, right Object, op token.Kind, expecting ast.Type) Object {
|
||||
match op {
|
||||
.and {
|
||||
if left is bool && right is bool {
|
||||
return left && right
|
||||
}
|
||||
e.error('invalid operands to &&: ${left.type_name()} and ${right.type_name()}')
|
||||
}
|
||||
.logical_or {
|
||||
if left is bool && right is bool {
|
||||
return left || right
|
||||
}
|
||||
e.error('invalid operands to ||: ${left.type_name()} and ${right.type_name()}')
|
||||
}
|
||||
.gt {
|
||||
match left {
|
||||
Int {
|
||||
@ -120,6 +132,120 @@ fn (e &Eval) infix_expr(left Object, right Object, op token.Kind, expecting ast.
|
||||
}
|
||||
}
|
||||
}
|
||||
.ge {
|
||||
match left {
|
||||
Int {
|
||||
match right {
|
||||
Int { return left.val >= right.val }
|
||||
Uint { return left.val >= right.val }
|
||||
Float { return left.val >= right.val }
|
||||
i64 { return left.val >= right }
|
||||
f64 { return left.val >= right }
|
||||
else { e.error('invalid operands to >=: Int and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
Uint {
|
||||
match right {
|
||||
Int { return left.val >= right.val }
|
||||
Uint { return left.val >= right.val }
|
||||
Float { return left.val >= right.val }
|
||||
i64 { return left.val >= right }
|
||||
f64 { return left.val >= right }
|
||||
else { e.error('invalid operands to >=: Uint and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
Float {
|
||||
match right {
|
||||
Int { return left.val >= right.val }
|
||||
Uint { return left.val >= right.val }
|
||||
Float { return left.val >= right.val }
|
||||
i64 { return left.val >= right }
|
||||
f64 { return left.val >= right }
|
||||
else { e.error('invalid operands to >=: Float and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
i64 {
|
||||
match right {
|
||||
Int { return left >= right.val }
|
||||
Uint { return left >= right.val }
|
||||
Float { return left >= right.val }
|
||||
i64 { return left >= right }
|
||||
f64 { return left >= right }
|
||||
else { e.error('invalid operands to >=: int literal and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
f64 {
|
||||
match right {
|
||||
Int { return left >= right.val }
|
||||
Uint { return left >= right.val }
|
||||
Float { return left >= right.val }
|
||||
i64 { return left >= right }
|
||||
f64 { return left >= right }
|
||||
else { e.error('invalid operands to >=: float literal and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
else {
|
||||
e.error('invalid operands to >=: ${left.type_name()} and ${right.type_name()}')
|
||||
}
|
||||
}
|
||||
}
|
||||
.le {
|
||||
match left {
|
||||
Int {
|
||||
match right {
|
||||
Int { return left.val <= right.val }
|
||||
Uint { return left.val <= right.val }
|
||||
Float { return left.val <= right.val }
|
||||
i64 { return left.val <= right }
|
||||
f64 { return left.val <= right }
|
||||
else { e.error('invalid operands to <=: Int and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
Uint {
|
||||
match right {
|
||||
Int { return left.val <= right.val }
|
||||
Uint { return left.val <= right.val }
|
||||
Float { return left.val <= right.val }
|
||||
i64 { return left.val <= right }
|
||||
f64 { return left.val <= right }
|
||||
else { e.error('invalid operands to <=: Uint and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
Float {
|
||||
match right {
|
||||
Int { return left.val <= right.val }
|
||||
Uint { return left.val <= right.val }
|
||||
Float { return left.val <= right.val }
|
||||
i64 { return left.val <= right }
|
||||
f64 { return left.val <= right }
|
||||
else { e.error('invalid operands to <=: Float and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
i64 {
|
||||
match right {
|
||||
Int { return left <= right.val }
|
||||
Uint { return left <= right.val }
|
||||
Float { return left <= right.val }
|
||||
i64 { return left <= right }
|
||||
f64 { return left <= right }
|
||||
else { e.error('invalid operands to <=: int literal and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
f64 {
|
||||
match right {
|
||||
Int { return left <= right.val }
|
||||
Uint { return left <= right.val }
|
||||
Float { return left <= right.val }
|
||||
i64 { return left <= right }
|
||||
f64 { return left <= right }
|
||||
else { e.error('invalid operands to <=: float literal and ${right.type_name()}') }
|
||||
}
|
||||
}
|
||||
else {
|
||||
e.error('invalid operands to <=: ${left.type_name()} and ${right.type_name()}')
|
||||
}
|
||||
}
|
||||
}
|
||||
.eq {
|
||||
match left {
|
||||
Int {
|
||||
|
@ -4,10 +4,16 @@ import v.ast
|
||||
import v.token
|
||||
|
||||
pub fn (mut e Eval) stmts(stmts []ast.Stmt) {
|
||||
if e.executed_return_stmt {
|
||||
return
|
||||
}
|
||||
e.open_scope()
|
||||
for stmt in stmts {
|
||||
e.stmt(stmt)
|
||||
if e.returning {
|
||||
if !e.executed_return_stmt {
|
||||
e.stmt(stmt)
|
||||
}
|
||||
if stmt is ast.Return {
|
||||
e.executed_return_stmt = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -47,3 +47,24 @@ fn test_comptime_if_without_func() {
|
||||
dump(ret)
|
||||
assert ret == []
|
||||
}
|
||||
|
||||
fn test_comptime_if_infix() {
|
||||
mut e := eval.create()
|
||||
|
||||
ret := e.run('const a =
|
||||
\$if amd64 || aarch64 || arm64 || rv64 { "64bit" }
|
||||
\$else \$if i386 || arm32 || rv32 { "32bit" }
|
||||
\$else \$if s390x { "s390x" }
|
||||
\$else \$if ppc64le { "ppc64le" }
|
||||
\$else \$if loongarch64 { "loongarch64" }
|
||||
\$else { "unknown" }
|
||||
|
||||
const b = 1.5
|
||||
|
||||
fn display() (string,f64) { println(a) println(b) return a,b } display()')!
|
||||
|
||||
dump(ret)
|
||||
assert ret[0].string().len != 0
|
||||
assert ret[0].string() != 'unknown'
|
||||
assert ret[1].float_val() == 1.5
|
||||
}
|
||||
|
@ -29,3 +29,46 @@ fn test_if_return() {
|
||||
dump(ret1)
|
||||
assert ret1[0].int_val() == 666
|
||||
}
|
||||
|
||||
fn test_if_infix_return_early() {
|
||||
mut e := eval.create()
|
||||
|
||||
ret := e.run('
|
||||
fn display(a int, b int) int {
|
||||
mut k := false
|
||||
if !k {
|
||||
k = !k
|
||||
}
|
||||
println(k)
|
||||
if a == 100 && b == 100 {
|
||||
return 100
|
||||
} else if a == 100 && b != 100 {
|
||||
return 101
|
||||
} else if a == 100 && b > 100 {
|
||||
return 102
|
||||
} else if a == 100 && b < 100 {
|
||||
return 103
|
||||
} else if a == 100 && b >= 100 {
|
||||
return 104
|
||||
} else if a == 100 && b <= 100 {
|
||||
return 105
|
||||
} else if a == 100 || b == 100 {
|
||||
return 106
|
||||
} else if a == 100 || b != 100 {
|
||||
return 107
|
||||
} else if a == 100 || b > 100 {
|
||||
return 108
|
||||
} else if a == 100 || b < 100 {
|
||||
return 109
|
||||
} else if a == 100 || b >= 100 {
|
||||
return 110
|
||||
} else if a == 100 || b <= 100 {
|
||||
return 111
|
||||
}
|
||||
return 7171
|
||||
}
|
||||
display(200, 101)')!
|
||||
|
||||
dump(ret)
|
||||
assert ret[0].int_val() == 107
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user