eval: add comptime-if support (#24919)

This commit is contained in:
kbkpbot 2025-07-17 22:52:41 +08:00 committed by GitHub
parent 54e8ed5ec5
commit a1b7f5485f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 125 additions and 36 deletions

View File

@ -202,15 +202,104 @@ pub fn (mut e Eval) register_symbol_stmts(stmts []ast.Stmt, mod string, file str
pub fn (mut e Eval) comptime_cond(cond ast.Expr) bool {
match cond {
ast.Ident {
match cond.name {
'native' {
return false
cname := cond.name
if cname in ast.valid_comptime_if_os {
mut ident_result := false
if !e.pref.output_cross_c {
if cname_enum_val := pref.os_from_string(cname) {
if cname_enum_val == e.pref.os {
ident_result = true
}
}
}
'windows' {
return e.pref.os == .windows
$if trace_comptime_os_checks ? {
eprintln('>>> ident_name: ${ident_name} | e.pref.os: ${e.pref.os} | ident_result: ${ident_result}')
}
else {
e.error('unknown compile time if')
return ident_result
} else if cname in ast.valid_comptime_if_compilers {
return pref.cc_from_string(cname) == e.pref.ccompiler_type
} else if cname in ast.valid_comptime_if_platforms {
match cname {
'amd64' { return e.pref.arch == .amd64 }
'i386' { return e.pref.arch == .i386 }
'aarch64' { return e.pref.arch == .arm64 }
'arm64' { return e.pref.arch == .arm64 }
'arm32' { return e.pref.arch == .arm32 }
'rv64' { return e.pref.arch == .rv64 }
'rv32' { return e.pref.arch == .rv32 }
's390x' { return e.pref.arch == .s390x }
'ppc64le' { return e.pref.arch == .ppc64le }
'loongarch64' { return e.pref.arch == .loongarch64 }
else { e.error('unknown comptime platforms \$if ${cname}') }
}
} else if cname in ast.valid_comptime_if_cpu_features {
match cname {
'x64' { e.pref.m64 }
'x32' { !e.pref.m64 }
else { e.error('unknown comptime cpu features \$if ${cname}') }
}
} else if cname in ast.valid_comptime_if_other {
match cname {
'apk' {
return e.pref.is_apk
}
'js' {
return e.pref.backend.is_js()
}
'debug' {
return e.pref.is_debug
}
'prod' {
return e.pref.is_prod
}
'profile' {
return e.pref.is_prof
}
'test' {
return e.pref.is_test
}
'musl' {
e.error('unknown comptime other \$if ${cname}')
}
'glibc' {
e.error('unknown comptime other \$if ${cname}')
}
'threads' {
return e.table.gostmts > 0
}
'prealloc' {
return e.pref.prealloc
}
'no_bounds_checking' {
return cname in e.pref.compile_defines_all
}
'autofree' {
return e.pref.autofree
}
'freestanding' {
return e.pref.is_bare && !e.pref.output_cross_c
}
'interpreter' {
return e.pref.backend == .interpret
}
'es5' {
return e.pref.output_es5
}
'wasm32' {
return e.pref.os == .wasm32
}
'wasm32_wasi' {
return e.pref.os == .wasm32_wasi
}
'fast_math' {
return e.pref.fast_math
}
'native' {
return e.pref.backend == .native
}
else {
e.error('unknown comptime other \$if ${cname}')
}
}
}
}

View File

@ -1,6 +1,5 @@
module eval
import v.pref
import v.ast
import v.util
import math
@ -145,36 +144,13 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object {
return Object(res)
}
ast.IfExpr {
if expr.is_expr {
e.error('`if` expressions not supported')
}
if expr.is_comptime {
for i, branch in expr.branches {
mut do_if := false
if expr.has_else && i + 1 == expr.branches.len { // else branch
do_if = true
} else {
if branch.cond is ast.Ident {
if known_os := pref.os_from_string(branch.cond.name) {
do_if = e.pref.os == known_os
} else {
match branch.cond.name {
'prealloc' {
do_if = e.pref.prealloc
}
else {
e.error('unknown compile time if: ${branch.cond.name}')
}
}
}
} else if branch.cond is ast.PostfixExpr {
do_if = (branch.cond.expr as ast.Ident).name in e.pref.compile_defines
}
}
if do_if {
if e.comptime_cond(branch.cond) || expr.branches.len == i + 1 {
e.returning = true
e.return_values = []
e.stmts(branch.stmts)
break
return e.return_values[0]
}
}
return empty

View File

@ -17,7 +17,10 @@ pub fn (mut e Eval) stmts(stmts []ast.Stmt) {
pub fn (mut e Eval) stmt(stmt ast.Stmt) {
match stmt {
ast.ExprStmt {
e.expr(stmt.expr, stmt.typ)
ret := e.expr(stmt.expr, stmt.typ)
if e.returning {
e.return_values << ret
}
}
ast.AssignStmt {
// if stmt.left.len != 1 {

View File

@ -0,0 +1,21 @@
import v.eval
fn test_comptime_if() {
mut e := eval.create()
ret := e.run('const a =
\$if amd64 { "amd" }
\$else \$if i386 { "i386" }
\$else \$if aarch64 { "aarch64" }
\$else \$if arm64 { "arm64" }
\$else \$if arm32 { "arm32" }
\$else \$if rv64 { "rv64" }
\$else \$if rv32 { "rv32" }
\$else \$if s390x { "s390x" }
\$else \$if ppc64le { "ppc64le" }
\$else \$if loongarch64 { "loongarch64" }
\$else { "unknown" }')!
dump(ret)
assert ret[0].string().len != 0
assert ret[0].string() != 'unknown'
}