extract common code from checker and parser

This commit is contained in:
kbkpbot 2025-09-02 12:16:10 +08:00
parent 6cd6832ed5
commit 2c4dfb5ff5
3 changed files with 237 additions and 462 deletions

View file

@ -1,5 +1,7 @@
module ast
import v.pref
pub const valid_comptime_if_os = ['windows', 'ios', 'macos', 'mach', 'darwin', 'hpux', 'gnu', 'qnx',
'linux', 'freebsd', 'openbsd', 'netbsd', 'bsd', 'dragonfly', 'android', 'termux', 'solaris',
'haiku', 'serenity', 'vinix', 'plan9', 'wasm32_emscripten']
@ -22,3 +24,225 @@ fn all_valid_comptime_idents() []string {
res << valid_comptime_if_other
return res
}
pub fn eval_comptime_not_user_defined_ident(ident string, the_pref &pref.Preferences) !bool {
mut is_true := false
if ident in valid_comptime_if_os {
if ident_enum_val := pref.os_from_string(ident) {
if ident_enum_val == the_pref.os {
is_true = true
}
}
} else if ident in valid_comptime_if_compilers {
is_true = pref.cc_from_string(ident) == the_pref.ccompiler_type
} else if ident in valid_comptime_if_platforms {
match ident {
'amd64' {
is_true = the_pref.arch == .amd64
}
'i386' {
is_true = the_pref.arch == .i386
}
'aarch64' {
is_true = the_pref.arch == .arm64
}
'arm64' {
is_true = the_pref.arch == .arm64
}
'arm32' {
is_true = the_pref.arch == .arm32
}
'rv64' {
is_true = the_pref.arch == .rv64
}
'rv32' {
is_true = the_pref.arch == .rv32
}
's390x' {
is_true = the_pref.arch == .s390x
}
'ppc64le' {
is_true = the_pref.arch == .ppc64le
}
'loongarch64' {
is_true = the_pref.arch == .loongarch64
}
else {
return error('invalid \$if condition: unknown platforms `${ident}`')
}
}
} else if ident in valid_comptime_if_cpu_features {
match ident {
'x64' {
is_true = the_pref.m64
}
'x32' {
is_true = !the_pref.m64
}
'little_endian' {
is_true = $if little_endian { true } $else { false }
}
'big_endian' {
is_true = $if big_endian { true } $else { false }
}
else {
return error('invalid \$if condition: unknown cpu_features `${ident}`')
}
}
} else if ident in valid_comptime_if_other {
match ident {
'apk' {
is_true = the_pref.is_apk
}
'js' {
is_true = the_pref.backend.is_js()
}
'debug' {
is_true = the_pref.is_debug
}
'prod' {
is_true = the_pref.is_prod
}
'test' {
is_true = the_pref.is_test
}
'glibc' {
is_true = the_pref.is_glibc
}
'prealloc' {
is_true = the_pref.prealloc
}
'no_bounds_checking' {
is_true = the_pref.no_bounds_checking
}
'freestanding' {
is_true = the_pref.is_bare && !the_pref.output_cross_c
}
'threads' {
return error('threads should handle outside of `check_valid_ident()`')
}
'js_node' {
is_true = the_pref.backend == .js_node
}
'js_browser' {
is_true = the_pref.backend == .js_browser
}
'js_freestanding' {
is_true = the_pref.backend == .js_freestanding
}
'interpreter' {
is_true = the_pref.backend == .interpret
}
'es5' {
is_true = the_pref.output_es5
}
'profile' {
is_true = the_pref.is_prof
}
'wasm32' {
is_true = the_pref.arch == .wasm32
}
'wasm32_wasi' {
is_true = the_pref.os == .wasm32_wasi
}
'fast_math' {
is_true = the_pref.fast_math
}
'native' {
is_true = the_pref.backend == .native
}
'autofree' {
is_true = the_pref.autofree
}
else {
return error('invalid \$if condition: unknown other indent `${ident}`')
}
}
} else if ident in the_pref.compile_defines {
is_true = true
} else {
return error('invalid \$if condition: unknown indent `${ident}`')
}
return is_true
}
pub const system_ident_map = {
// OS
'windows': '_WIN32'
'ios': '__TARGET_IOS__'
'macos': '__APPLE__'
'mach': '__MACH__'
'darwin': '__DARWIN__'
'hpux': '__HPUX__'
'gnu': '__GNU__'
'qnx': '__QNX__'
'linux': '__linux__'
'serenity': '__serenity__'
'plan9': '__plan9__'
'vinix': '__vinix__'
'freebsd': '__FreeBSD__'
'openbsd': '__OpenBSD__'
'netbsd': '__NetBSD__'
'bsd': '__BSD__'
'dragonfly': '__DragonFly__'
'android': '__ANDROID__'
'termux': '__TERMUX__'
'solaris': '__sun'
'haiku': '__HAIKU__'
// Backend
'js': '_VJS'
'wasm32_emscripten': '__EMSCRIPTEN__'
'native': '_VNATIVE'
// Compiler
'gcc': '__V_GCC__'
'tinyc': '__TINYC__'
'clang': '__clang__'
'mingw': '__MINGW32__'
'msvc': '_MSC_VER'
'cplusplus': '__cplusplus'
// Others
'threads': '__VTHREADS__'
'gcboehm': '_VGCBOEHM'
'debug': '_VDEBUG'
'prod': '_VPROD'
'profile': '_VPROFILE'
'test': '_VTEST'
'glibc': '__GLIBC__'
'prealloc': '_VPREALLOC'
'no_bounds_checking': 'CUSTOM_DEFINE_no_bounds_checking'
'freestanding': '_VFREESTANDING'
'autofree': '_VAUTOFREE'
// CPU
'amd64': '__V_amd64'
'aarch64': '__V_arm64'
'arm64': '__V_arm64' // aarch64 alias
'arm32': '__V_arm32'
'i386': '__V_x86'
'rv64': '__V_rv64'
'riscv64': '__V_rv64' // rv64 alias
'rv32': '__V_rv32'
'riscv32': '__V_rv32' // rv32 alias
's390x': '__V_s390x'
'ppc64le': '__V_ppc64le'
'loongarch64': '__V_loongarch64'
'x64': 'TARGET_IS_64BIT'
'x32': 'TARGET_IS_32BIT'
'little_endian': 'TARGET_ORDER_IS_LITTLE'
'big_endian': 'TARGET_ORDER_IS_BIG'
}
pub fn comptime_if_to_ifdef(name string, the_pref &pref.Preferences) !string {
if name == 'fast_math' {
return if the_pref.ccompiler_type == .msvc {
// turned on by: `-cflags /fp:fast`
'_M_FP_FAST'
} else {
// turned on by: `-cflags -ffast-math`
'__FAST_MATH__'
}
}
if ifdef := system_ident_map[name] {
return ifdef
}
return error('bad os ifdef name `${name}`')
}

View file

@ -784,191 +784,6 @@ fn (mut c Checker) evaluate_once_comptime_if_attribute(mut node ast.Attr) bool {
return node.ct_skip
}
fn (mut c Checker) comptime_if_to_ifdef(name string) !string {
match name {
// platforms/os-es:
'windows' {
return '_WIN32'
}
'ios' {
return '__TARGET_IOS__'
}
'macos' {
return '__APPLE__'
}
'mach' {
return '__MACH__'
}
'darwin' {
return '__DARWIN__'
}
'hpux' {
return '__HPUX__'
}
'gnu' {
return '__GNU__'
}
'qnx' {
return '__QNX__'
}
'linux' {
return '__linux__'
}
'serenity' {
return '__serenity__'
}
'plan9' {
return '__plan9__'
}
'vinix' {
return '__vinix__'
}
'freebsd' {
return '__FreeBSD__'
}
'openbsd' {
return '__OpenBSD__'
}
'netbsd' {
return '__NetBSD__'
}
'bsd' {
return '__BSD__'
}
'dragonfly' {
return '__DragonFly__'
}
'android' {
return '__ANDROID__'
}
'termux' {
// Note: termux is running on Android natively so __ANDROID__ will also be defined
return '__TERMUX__'
}
'solaris' {
return '__sun'
}
'haiku' {
return '__HAIKU__'
}
//
'js' {
return '_VJS'
}
'wasm32_emscripten' {
return '__EMSCRIPTEN__'
}
'native' {
return '_VNATIVE' // when using the native backend, cgen is inactive
}
// compilers:
'gcc' {
return '__V_GCC__'
}
'tinyc' {
return '__TINYC__'
}
'clang' {
return '__clang__'
}
'mingw' {
return '__MINGW32__'
}
'msvc' {
return '_MSC_VER'
}
'cplusplus' {
return '__cplusplus'
}
// other:
'threads' {
return '__VTHREADS__'
}
'gcboehm' {
return '_VGCBOEHM'
}
'debug' {
return '_VDEBUG'
}
'prod' {
return '_VPROD'
}
'profile' {
return '_VPROFILE'
}
'test' {
return '_VTEST'
}
'glibc' {
return '__GLIBC__'
}
'prealloc' {
return '_VPREALLOC'
}
'no_bounds_checking' {
return 'CUSTOM_DEFINE_no_bounds_checking'
}
'freestanding' {
return '_VFREESTANDING'
}
'autofree' {
return '_VAUTOFREE'
}
// architectures:
'amd64' {
return '__V_amd64'
}
'aarch64', 'arm64' {
return '__V_arm64'
}
'arm32' {
return '__V_arm32'
}
'i386' {
return '__V_x86'
}
'rv64', 'riscv64' {
return '__V_rv64'
}
'rv32', 'riscv32' {
return '__V_rv32'
}
's390x' {
return '__V_s390x'
}
'ppc64le' {
return '__V_ppc64le'
}
'loongarch64' {
return '__V_loongarch64'
}
// bitness:
'x64' {
return 'TARGET_IS_64BIT'
}
'x32' {
return 'TARGET_IS_32BIT'
}
// endianness:
'little_endian' {
return 'TARGET_ORDER_IS_LITTLE'
}
'big_endian' {
return 'TARGET_ORDER_IS_BIG'
}
'fast_math' {
if c.pref.ccompiler_type == .msvc {
// turned on by: `-cflags /fp:fast`
return '_M_FP_FAST'
}
// turned on by: `-cflags -ffast-math`
return '__FAST_MATH__'
}
else {}
}
return error('bad os ifdef name "${name}"')
}
// check if `ident` is a function generic, such as `T`
fn (mut c Checker) is_generic_ident(ident string) bool {
if !isnil(c.table.cur_fn) && ident in c.table.cur_fn.generic_names
@ -1141,10 +956,6 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, mut sb strings.Builder) (
should_record_ident = true
is_user_ident = true
ident_name = cname
// ifdef := c.comptime_if_to_ifdef(cname, true) or {
// c.error(err.msg(), cond.pos)
// return false, false
//}
sb.write_string('defined(CUSTOM_DEFINE_${cname})')
is_true = cname in c.pref.compile_defines
return is_true, false
@ -1483,143 +1294,12 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, mut sb strings.Builder) (
should_record_ident = true
is_user_ident = false
ident_name = cname
if cname in ast.valid_comptime_if_os {
if cname_enum_val := pref.os_from_string(cname) {
if cname_enum_val == c.pref.os {
is_true = true
}
}
} else if cname in ast.valid_comptime_if_compilers {
is_true = pref.cc_from_string(cname) == c.pref.ccompiler_type
} else if cname in ast.valid_comptime_if_platforms {
if cname == 'aarch64' {
c.note('use `arm64` instead of `aarch64`', cond.pos)
}
match cname {
'amd64' {
is_true = c.pref.arch == .amd64
}
'i386' {
is_true = c.pref.arch == .i386
}
'aarch64' {
is_true = c.pref.arch == .arm64
}
'arm64' {
is_true = c.pref.arch == .arm64
}
'arm32' {
is_true = c.pref.arch == .arm32
}
'rv64' {
is_true = c.pref.arch == .rv64
}
'rv32' {
is_true = c.pref.arch == .rv32
}
's390x' {
is_true = c.pref.arch == .s390x
}
'ppc64le' {
is_true = c.pref.arch == .ppc64le
}
'loongarch64' {
is_true = c.pref.arch == .loongarch64
}
else {
c.error('invalid \$if condition: unknown platforms `${cname}`',
cond.pos)
return false, false
}
}
} else if cname in ast.valid_comptime_if_cpu_features {
match cname {
'x64' {
is_true = c.pref.m64
}
'x32' {
is_true = !c.pref.m64
}
'little_endian' {
is_true = $if little_endian { true } $else { false }
}
'big_endian' {
is_true = $if big_endian { true } $else { false }
}
else {
c.error('invalid \$if condition: unknown cpu_features `${cname}`',
cond.pos)
return false, false
}
}
} else if cname in ast.valid_comptime_if_other {
match cname {
'apk' {
is_true = c.pref.is_apk
}
'js' {
is_true = c.pref.backend.is_js()
}
'debug' {
is_true = c.pref.is_debug
}
'prod' {
is_true = c.pref.is_prod
}
'test' {
is_true = c.pref.is_test
}
'glibc' {
is_true = c.pref.is_glibc
}
'prealloc' {
is_true = c.pref.prealloc
}
'no_bounds_checking' {
is_true = c.pref.no_bounds_checking
}
'freestanding' {
is_true = c.pref.is_bare && !c.pref.output_cross_c
}
'threads' {
if cname in ast.valid_comptime_not_user_defined {
if cname == 'threads' {
is_true = c.table.gostmts > 0
}
'js_node' {
is_true = c.pref.backend == .js_node
}
'js_browser' {
is_true = c.pref.backend == .js_browser
}
'js_freestanding' {
is_true = c.pref.backend == .js_freestanding
}
'interpreter' {
is_true = c.pref.backend == .interpret
}
'es5' {
is_true = c.pref.output_es5
}
'profile' {
is_true = c.pref.is_prof
}
'wasm32' {
is_true = c.pref.arch == .wasm32
}
'wasm32_wasi' {
is_true = c.pref.os == .wasm32_wasi
}
'fast_math' {
is_true = c.pref.fast_math
}
'native' {
is_true = c.pref.backend == .native
}
'autofree' {
is_true = c.pref.autofree
}
else {
c.error('invalid \$if condition: unknown other indent `${cname}`',
cond.pos)
} else {
is_true = ast.eval_comptime_not_user_defined_ident(cname, c.pref) or {
c.error(err.msg(), cond.pos)
return false, false
}
}
@ -1655,7 +1335,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, mut sb strings.Builder) (
c.error('invalid \$if condition: unknown indent `${cname}`', cond.pos)
return false, false
}
if ifdef := c.comptime_if_to_ifdef(cname) {
if ifdef := ast.comptime_if_to_ifdef(cname, c.pref) {
sb.write_string('defined(${ifdef})')
} else {
sb.write_string('${is_true}')

View file

@ -5,7 +5,6 @@ module parser
import v.ast
import v.token
import v.pref
import v.pkgconfig
fn (mut p Parser) if_expr(is_comptime bool, is_expr bool) ast.IfExpr {
@ -724,140 +723,12 @@ fn (mut p Parser) comptime_if_cond(mut cond ast.Expr) bool {
}
ast.Ident {
cname := cond.name
if cname in ast.valid_comptime_if_os {
if cname_enum_val := pref.os_from_string(cname) {
if cname_enum_val == p.pref.os {
is_true = true
}
}
} else if cname in ast.valid_comptime_if_compilers {
is_true = pref.cc_from_string(cname) == p.pref.ccompiler_type
} else if cname in ast.valid_comptime_if_platforms {
if cname == 'aarch64' {
p.note('use `arm64` instead of `aarch64`')
}
match cname {
'amd64' {
is_true = p.pref.arch == .amd64
}
'i386' {
is_true = p.pref.arch == .i386
}
'aarch64' {
is_true = p.pref.arch == .arm64
}
'arm64' {
is_true = p.pref.arch == .arm64
}
'arm32' {
is_true = p.pref.arch == .arm32
}
'rv64' {
is_true = p.pref.arch == .rv64
}
'rv32' {
is_true = p.pref.arch == .rv32
}
's390x' {
is_true = p.pref.arch == .s390x
}
'ppc64le' {
is_true = p.pref.arch == .ppc64le
}
'loongarch64' {
is_true = p.pref.arch == .loongarch64
}
else {
p.error('invalid \$if condition: unknown platforms `${cname}`')
return false
}
}
} else if cname in ast.valid_comptime_if_cpu_features {
match cname {
'x64' {
is_true = p.pref.m64
}
'x32' {
is_true = !p.pref.m64
}
'little_endian' {
is_true = $if little_endian { true } $else { false }
}
'big_endian' {
is_true = $if big_endian { true } $else { false }
}
else {
p.error('invalid \$if condition: unknown cpu_features `${cname}`')
return false
}
}
} else if cname in ast.valid_comptime_if_other {
match cname {
'apk' {
is_true = p.pref.is_apk
}
'js' {
is_true = p.pref.backend.is_js()
}
'debug' {
is_true = p.pref.is_debug
}
'prod' {
is_true = p.pref.is_prod
}
'test' {
is_true = p.pref.is_test
}
'glibc' {
is_true = p.pref.is_glibc
}
'prealloc' {
is_true = p.pref.prealloc
}
'no_bounds_checking' {
is_true = p.pref.no_bounds_checking
}
'freestanding' {
is_true = p.pref.is_bare && !p.pref.output_cross_c
}
'threads' {
if cname in ast.valid_comptime_not_user_defined {
if cname == 'threads' {
is_true = p.table.gostmts > 0
}
'js_node' {
is_true = p.pref.backend == .js_node
}
'js_browser' {
is_true = p.pref.backend == .js_browser
}
'js_freestanding' {
is_true = p.pref.backend == .js_freestanding
}
'interpreter' {
is_true = p.pref.backend == .interpret
}
'es5' {
is_true = p.pref.output_es5
}
'profile' {
is_true = p.pref.is_prof
}
'wasm32' {
is_true = p.pref.arch == .wasm32
}
'wasm32_wasi' {
is_true = p.pref.os == .wasm32_wasi
}
'fast_math' {
is_true = p.pref.fast_math
}
'native' {
is_true = p.pref.backend == .native
}
'autofree' {
is_true = p.pref.autofree
}
else {
p.error('invalid \$if condition: unknown other indent `${cname}`')
} else {
is_true = ast.eval_comptime_not_user_defined_ident(cname, p.pref) or {
p.error(err.msg())
return false
}
}