diff --git a/vlib/v/eval/eval.v b/vlib/v/eval/eval.v index 18e8337494..de690bc57f 100644 --- a/vlib/v/eval/eval.v +++ b/vlib/v/eval/eval.v @@ -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}') + } } } } diff --git a/vlib/v/eval/expr.c.v b/vlib/v/eval/expr.c.v index 0656528a0b..23188bc8df 100644 --- a/vlib/v/eval/expr.c.v +++ b/vlib/v/eval/expr.c.v @@ -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 diff --git a/vlib/v/eval/stmt.v b/vlib/v/eval/stmt.v index d2d983a2ee..2582b4100e 100644 --- a/vlib/v/eval/stmt.v +++ b/vlib/v/eval/stmt.v @@ -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 { diff --git a/vlib/v/eval/tests/comptime_if_test.v b/vlib/v/eval/tests/comptime_if_test.v new file mode 100644 index 0000000000..1f587c2f3c --- /dev/null +++ b/vlib/v/eval/tests/comptime_if_test.v @@ -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' +}