160 lines
4.5 KiB
V
160 lines
4.5 KiB
V
module checker
|
|
|
|
import v.ast
|
|
|
|
fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue {
|
|
if nlevel > 100 {
|
|
// protect against a too deep comptime eval recursion
|
|
return none
|
|
}
|
|
match expr {
|
|
ast.IntegerLiteral {
|
|
x := expr.val.u64()
|
|
if x > 9223372036854775807 {
|
|
return x
|
|
}
|
|
return expr.val.i64()
|
|
}
|
|
ast.StringLiteral {
|
|
return expr.val
|
|
}
|
|
ast.CharLiteral {
|
|
runes := expr.val.runes()
|
|
if runes.len > 0 {
|
|
return runes[0]
|
|
}
|
|
return none
|
|
}
|
|
ast.Ident {
|
|
if expr.obj is ast.ConstField {
|
|
// an existing constant?
|
|
return eval_comptime_const_expr(expr.obj.expr, nlevel + 1)
|
|
}
|
|
}
|
|
ast.CastExpr {
|
|
cast_expr_value := eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none }
|
|
if expr.typ == ast.i8_type {
|
|
return cast_expr_value.i8() or { return none }
|
|
}
|
|
if expr.typ == ast.i16_type {
|
|
return cast_expr_value.i16() or { return none }
|
|
}
|
|
if expr.typ == ast.int_type {
|
|
return cast_expr_value.int() or { return none }
|
|
}
|
|
if expr.typ == ast.i64_type {
|
|
return cast_expr_value.i64() or { return none }
|
|
}
|
|
//
|
|
if expr.typ == ast.byte_type {
|
|
return cast_expr_value.byte() or { return none }
|
|
}
|
|
if expr.typ == ast.u16_type {
|
|
return cast_expr_value.u16() or { return none }
|
|
}
|
|
if expr.typ == ast.u32_type {
|
|
return cast_expr_value.u32() or { return none }
|
|
}
|
|
if expr.typ == ast.u64_type {
|
|
return cast_expr_value.u64() or { return none }
|
|
}
|
|
//
|
|
if expr.typ == ast.f32_type {
|
|
return cast_expr_value.f32() or { return none }
|
|
}
|
|
if expr.typ == ast.f64_type {
|
|
return cast_expr_value.f64() or { return none }
|
|
}
|
|
}
|
|
ast.InfixExpr {
|
|
left := eval_comptime_const_expr(expr.left, nlevel + 1) ?
|
|
right := eval_comptime_const_expr(expr.right, nlevel + 1) ?
|
|
if left is string && right is string {
|
|
match expr.op {
|
|
.plus {
|
|
return left + right
|
|
}
|
|
else {
|
|
return none
|
|
}
|
|
}
|
|
} else if left is u64 && right is i64 {
|
|
match expr.op {
|
|
.plus { return i64(left) + i64(right) }
|
|
.minus { return i64(left) - i64(right) }
|
|
.mul { return i64(left) * i64(right) }
|
|
.div { return i64(left) / i64(right) }
|
|
.mod { return i64(left) % i64(right) }
|
|
.xor { return i64(left) ^ i64(right) }
|
|
.pipe { return i64(left) | i64(right) }
|
|
.amp { return i64(left) & i64(right) }
|
|
.left_shift { return i64(left) << i64(right) }
|
|
.right_shift { return i64(left) >> i64(right) }
|
|
else { return none }
|
|
}
|
|
} else if left is i64 && right is u64 {
|
|
match expr.op {
|
|
.plus { return i64(left) + i64(right) }
|
|
.minus { return i64(left) - i64(right) }
|
|
.mul { return i64(left) * i64(right) }
|
|
.div { return i64(left) / i64(right) }
|
|
.mod { return i64(left) % i64(right) }
|
|
.xor { return i64(left) ^ i64(right) }
|
|
.pipe { return i64(left) | i64(right) }
|
|
.amp { return i64(left) & i64(right) }
|
|
.left_shift { return i64(left) << i64(right) }
|
|
.right_shift { return i64(left) >> i64(right) }
|
|
else { return none }
|
|
}
|
|
} else if left is u64 && right is u64 {
|
|
match expr.op {
|
|
.plus { return left + right }
|
|
.minus { return left - right }
|
|
.mul { return left * right }
|
|
.div { return left / right }
|
|
.mod { return left % right }
|
|
.xor { return left ^ right }
|
|
.pipe { return left | right }
|
|
.amp { return left & right }
|
|
.left_shift { return left << right }
|
|
.right_shift { return left >> right }
|
|
else { return none }
|
|
}
|
|
} else if left is i64 && right is i64 {
|
|
match expr.op {
|
|
.plus { return left + right }
|
|
.minus { return left - right }
|
|
.mul { return left * right }
|
|
.div { return left / right }
|
|
.mod { return left % right }
|
|
.xor { return left ^ right }
|
|
.pipe { return left | right }
|
|
.amp { return left & right }
|
|
.left_shift { return left << right }
|
|
.right_shift { return left >> right }
|
|
else { return none }
|
|
}
|
|
} else if left is byte && right is byte {
|
|
match expr.op {
|
|
.plus { return left + right }
|
|
.minus { return left - right }
|
|
.mul { return left * right }
|
|
.div { return left / right }
|
|
.mod { return left % right }
|
|
.xor { return left ^ right }
|
|
.pipe { return left | right }
|
|
.amp { return left & right }
|
|
.left_shift { return left << right }
|
|
.right_shift { return left >> right }
|
|
else { return none }
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// eprintln('>>> nlevel: $nlevel | another $expr.type_name() | $expr ')
|
|
return none
|
|
}
|
|
}
|
|
return none
|
|
}
|