mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: support for compile-time conditionals (#15949)
This commit is contained in:
parent
b83d0281e4
commit
7993f0bf39
@ -2262,6 +2262,11 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||
g.gen_typeof_expr(node.right[i] as ast.TypeOf, true)
|
||||
g.mov_reg(.rsi, .rax)
|
||||
}
|
||||
ast.AtExpr {
|
||||
dest := g.allocate_var(name, 8, 0)
|
||||
g.learel(.rsi, g.allocate_string(g.comptime_at(right), 3, .rel32))
|
||||
g.mov_reg_to_var(LocalVar{dest, ast.u64_type_idx, name}, .rsi)
|
||||
}
|
||||
else {
|
||||
// dump(node)
|
||||
size := g.get_type_size(node.left_types[i])
|
||||
@ -2733,7 +2738,8 @@ fn (mut g Gen) condition(expr ast.Expr, neg bool) int {
|
||||
|
||||
fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||
if node.is_comptime {
|
||||
g.n_error('ignored comptime')
|
||||
g.comptime_conditional(node)
|
||||
return
|
||||
}
|
||||
if node.branches.len == 0 {
|
||||
return
|
||||
|
217
vlib/v/gen/native/comptime.v
Normal file
217
vlib/v/gen/native/comptime.v
Normal file
@ -0,0 +1,217 @@
|
||||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module native
|
||||
|
||||
import v.ast
|
||||
|
||||
fn (mut g Gen) comptime_at(node ast.AtExpr) string {
|
||||
return node.val
|
||||
}
|
||||
|
||||
fn (mut g Gen) comptime_conditional(node ast.IfExpr) {
|
||||
if node.branches.len == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for i, branch in node.branches {
|
||||
// handle $else branch, which does not have a condition
|
||||
if node.has_else && i + 1 == node.branches.len {
|
||||
g.stmts(branch.stmts)
|
||||
} else if g.comptime_is_truthy(branch.cond) {
|
||||
g.stmts(branch.stmts)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) comptime_is_truthy(cond ast.Expr) bool {
|
||||
match cond {
|
||||
ast.BoolLiteral {
|
||||
return cond.val
|
||||
}
|
||||
ast.ParExpr {
|
||||
return g.comptime_is_truthy(cond.expr)
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
match cond.op {
|
||||
.not {
|
||||
return !g.comptime_is_truthy(cond.right)
|
||||
}
|
||||
else {
|
||||
g.n_error('Compile time infix expr `$cond` is not handled by the native backed.')
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.PostfixExpr {
|
||||
return g.comptime_ident((cond.expr as ast.Ident).name, true)
|
||||
}
|
||||
ast.InfixExpr {
|
||||
match cond.op {
|
||||
.logical_or {
|
||||
return g.comptime_is_truthy(cond.left) || g.comptime_is_truthy(cond.right)
|
||||
}
|
||||
.and {
|
||||
return g.comptime_is_truthy(cond.left) && g.comptime_is_truthy(cond.right)
|
||||
}
|
||||
.eq {
|
||||
return g.comptime_is_truthy(cond.left) == g.comptime_is_truthy(cond.right)
|
||||
}
|
||||
.ne {
|
||||
return g.comptime_is_truthy(cond.left) != g.comptime_is_truthy(cond.right)
|
||||
}
|
||||
else {
|
||||
g.n_error('Compile time infix expr `$cond` is not handled by the native backend.')
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.Ident {
|
||||
return g.comptime_ident(cond.name, false)
|
||||
}
|
||||
ast.ComptimeCall {
|
||||
g.n_error('Comptime calls are not implemented')
|
||||
}
|
||||
else {
|
||||
// should be unreachable
|
||||
g.n_error('Compile time conditional `$cond` is not handled by the native backend.')
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fn (mut g Gen) comptime_ident(name string, is_comptime_optional bool) bool {
|
||||
return match name {
|
||||
//
|
||||
// Operating systems
|
||||
//
|
||||
'windows' {
|
||||
g.pref.os == .windows
|
||||
}
|
||||
'ios' {
|
||||
g.pref.os == .ios
|
||||
}
|
||||
'macos', 'mac', 'darwin' {
|
||||
g.pref.os == .macos
|
||||
}
|
||||
'linux' {
|
||||
g.pref.os == .linux
|
||||
}
|
||||
'serenity' {
|
||||
g.pref.os == .serenity
|
||||
}
|
||||
'vinix' {
|
||||
g.pref.os == .vinix
|
||||
}
|
||||
'freebsd' {
|
||||
g.pref.os == .freebsd
|
||||
}
|
||||
'openbsd' {
|
||||
g.pref.os == .openbsd
|
||||
}
|
||||
'netbsd' {
|
||||
g.pref.os == .netbsd
|
||||
}
|
||||
'bsd' {
|
||||
g.pref.os in [.freebsd, .openbsd, .netbsd]
|
||||
}
|
||||
'dragonfly' {
|
||||
g.pref.os == .dragonfly
|
||||
}
|
||||
'android' {
|
||||
g.pref.os == .android
|
||||
}
|
||||
'termux' {
|
||||
g.pref.os == .termux
|
||||
}
|
||||
'solaris' {
|
||||
g.pref.os == .solaris
|
||||
}
|
||||
'haiku' {
|
||||
g.pref.os == .haiku
|
||||
}
|
||||
//
|
||||
// C compilers, these will probably always be false
|
||||
//
|
||||
'gcc' {
|
||||
g.pref.ccompiler_type == .gcc
|
||||
}
|
||||
'tinyc' {
|
||||
g.pref.ccompiler_type == .tinyc
|
||||
}
|
||||
'clang' {
|
||||
g.pref.ccompiler_type == .clang
|
||||
}
|
||||
'mingw' {
|
||||
g.pref.ccompiler_type == .mingw
|
||||
}
|
||||
'msvc' {
|
||||
g.pref.ccompiler_type == .msvc
|
||||
}
|
||||
'cplusplus' {
|
||||
g.pref.ccompiler_type == .cplusplus
|
||||
}
|
||||
//
|
||||
// Platforms
|
||||
//
|
||||
'amd64', 'x64' {
|
||||
g.pref.arch == .amd64
|
||||
}
|
||||
'arm64' {
|
||||
g.pref.arch == .arm64
|
||||
}
|
||||
'x86' {
|
||||
false // native only supports 64-bit systems
|
||||
}
|
||||
'little_endian' {
|
||||
true // all systems targeted by native should be little-endian
|
||||
}
|
||||
'big_endian' {
|
||||
false // all systems targeted by native should be little-endian
|
||||
}
|
||||
//
|
||||
// Other
|
||||
//
|
||||
'debug' {
|
||||
g.pref.is_debug
|
||||
}
|
||||
'prod' {
|
||||
g.pref.is_prod
|
||||
}
|
||||
'test' {
|
||||
g.pref.is_test
|
||||
}
|
||||
'js' {
|
||||
g.pref.arch == .js_node
|
||||
}
|
||||
'glibc' {
|
||||
g.pref.is_glibc
|
||||
}
|
||||
'prealloc' {
|
||||
g.pref.prealloc
|
||||
}
|
||||
'no_bounds_checking' {
|
||||
false // TODO
|
||||
}
|
||||
'freestanding' {
|
||||
g.pref.arch == .js_freestanding
|
||||
}
|
||||
'no_segfault_handler' {
|
||||
false // TODO
|
||||
}
|
||||
'no_backtrace' {
|
||||
false // TODO
|
||||
}
|
||||
'no_main' {
|
||||
g.pref.is_script
|
||||
}
|
||||
else {
|
||||
if is_comptime_optional
|
||||
|| (g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all) {
|
||||
true
|
||||
} else {
|
||||
g.n_error('Unhandled os ifdef name "$name".')
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -811,13 +811,19 @@ g.expr
|
||||
g.v_error('struct.field selector not yet implemented for this backend', expr.pos)
|
||||
}
|
||||
ast.NodeError {}
|
||||
ast.AtExpr {
|
||||
if newline {
|
||||
g.gen_print(g.comptime_at(expr) + '\n', fd)
|
||||
} else {
|
||||
g.gen_print(g.comptime_at(expr), fd)
|
||||
}
|
||||
}
|
||||
/*
|
||||
ast.AnonFn {}
|
||||
ast.ArrayDecompose {}
|
||||
ast.ArrayInit {}
|
||||
ast.AsCast {}
|
||||
ast.Assoc {}
|
||||
ast.AtExpr {}
|
||||
ast.CTempVar {}
|
||||
ast.CastExpr {}
|
||||
ast.ChanInit {}
|
||||
@ -1326,7 +1332,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
}
|
||||
ast.IfExpr {
|
||||
if node.is_comptime {
|
||||
eprintln('Warning: ignored compile time conditional not yet supported for the native backend.')
|
||||
g.comptime_conditional(node)
|
||||
} else {
|
||||
g.if_expr(node)
|
||||
}
|
||||
|
13
vlib/v/gen/native/tests/atexpr.vv
Normal file
13
vlib/v/gen/native/tests/atexpr.vv
Normal file
@ -0,0 +1,13 @@
|
||||
fn abc() {
|
||||
// a comment
|
||||
a := @LINE
|
||||
b := @FILE_LINE
|
||||
c := @FN
|
||||
println(a)
|
||||
println(b)
|
||||
println(c)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
abc()
|
||||
}
|
3
vlib/v/gen/native/tests/atexpr.vv.out
Normal file
3
vlib/v/gen/native/tests/atexpr.vv.out
Normal file
@ -0,0 +1,3 @@
|
||||
3
|
||||
atexpr.vv:4
|
||||
abc
|
29
vlib/v/gen/native/tests/comptime.vv
Normal file
29
vlib/v/gen/native/tests/comptime.vv
Normal file
@ -0,0 +1,29 @@
|
||||
fn main() {
|
||||
comptime_if()
|
||||
}
|
||||
|
||||
fn comptime_if() {
|
||||
$if linux || windows || macos {
|
||||
println('linux or windows or macos')
|
||||
}
|
||||
|
||||
$if linux && windows {
|
||||
assert false
|
||||
}
|
||||
|
||||
$if custom_define ? {
|
||||
println('custom defines work')
|
||||
} $else {
|
||||
assert false
|
||||
}
|
||||
|
||||
$if test {
|
||||
println('test')
|
||||
} $else $if debug {
|
||||
println('debug')
|
||||
} $else $if prod {
|
||||
println('production')
|
||||
} $else {
|
||||
println('other')
|
||||
}
|
||||
}
|
3
vlib/v/gen/native/tests/comptime.vv.out
Normal file
3
vlib/v/gen/native/tests/comptime.vv.out
Normal file
@ -0,0 +1,3 @@
|
||||
linux or windows or macos
|
||||
custom defines work
|
||||
other
|
@ -40,7 +40,7 @@ fn test_native() {
|
||||
work_test_path := '$wrkdir/$test_file_name'
|
||||
exe_test_path := '$wrkdir/${test_file_name}.exe'
|
||||
tmperrfile := '$dir/${test}.tmperr'
|
||||
cmd := '${os.quoted_path(vexe)} -o ${os.quoted_path(exe_test_path)} -b native ${os.quoted_path(full_test_path)} 2> ${os.quoted_path(tmperrfile)}'
|
||||
cmd := '${os.quoted_path(vexe)} -o ${os.quoted_path(exe_test_path)} -b native ${os.quoted_path(full_test_path)} -d custom_define 2> ${os.quoted_path(tmperrfile)}'
|
||||
if is_verbose {
|
||||
println(cmd)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user