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)
|
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
|
returning bool
|
||||||
return_values []Object
|
return_values []Object
|
||||||
|
executed_return_stmt bool // already executed a return stmt in func
|
||||||
cur_mod string
|
cur_mod string
|
||||||
cur_file 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
|
scope_idx: e.scope_idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
e.executed_return_stmt = false
|
||||||
e.stmts(func.stmts)
|
e.stmts(func.stmts)
|
||||||
e.returning = false
|
e.returning = false
|
||||||
e.close_scope()
|
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 {
|
else {
|
||||||
e.error('unsupported expression')
|
e.error('unsupported expression')
|
||||||
}
|
}
|
||||||
|
@ -498,6 +498,9 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
|
|||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
match expr.op {
|
match expr.op {
|
||||||
|
.not {
|
||||||
|
return !(e.expr(expr.right, ast.bool_type) as bool)
|
||||||
|
}
|
||||||
.amp {
|
.amp {
|
||||||
x := e.expr(expr.right, expr.right_type)
|
x := e.expr(expr.right, expr.right_type)
|
||||||
return Ptr{
|
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 {
|
fn (e &Eval) infix_expr(left Object, right Object, op token.Kind, expecting ast.Type) Object {
|
||||||
match op {
|
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 {
|
.gt {
|
||||||
match left {
|
match left {
|
||||||
Int {
|
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 {
|
.eq {
|
||||||
match left {
|
match left {
|
||||||
Int {
|
Int {
|
||||||
|
@ -4,10 +4,16 @@ import v.ast
|
|||||||
import v.token
|
import v.token
|
||||||
|
|
||||||
pub fn (mut e Eval) stmts(stmts []ast.Stmt) {
|
pub fn (mut e Eval) stmts(stmts []ast.Stmt) {
|
||||||
|
if e.executed_return_stmt {
|
||||||
|
return
|
||||||
|
}
|
||||||
e.open_scope()
|
e.open_scope()
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
e.stmt(stmt)
|
if !e.executed_return_stmt {
|
||||||
if e.returning {
|
e.stmt(stmt)
|
||||||
|
}
|
||||||
|
if stmt is ast.Return {
|
||||||
|
e.executed_return_stmt = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,3 +47,24 @@ fn test_comptime_if_without_func() {
|
|||||||
dump(ret)
|
dump(ret)
|
||||||
assert 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)
|
dump(ret1)
|
||||||
assert ret1[0].int_val() == 666
|
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