| 1 | module ast |
| 2 | |
| 3 | import v.pref |
| 4 | |
| 5 | pub const valid_comptime_if_os = ['windows', 'ios', 'macos', 'mac', 'mach', 'darwin', 'hpux', 'gnu', |
| 6 | 'qnx', 'linux', 'freebsd', 'openbsd', 'netbsd', 'bsd', 'dragonfly', 'android', 'termux', |
| 7 | 'solaris', 'haiku', 'serenity', 'vinix', 'plan9', 'wasm32_emscripten'] |
| 8 | pub const valid_comptime_if_compilers = ['gcc', 'tinyc', 'clang', 'mingw', 'msvc', 'cplusplus'] |
| 9 | pub const valid_comptime_if_platforms = ['amd64', 'i386', 'aarch64', 'arm64', 'arm32', 'rv64', |
| 10 | 'rv32', 's390x', 'ppc64le', 'loongarch64', 'sparc64', 'ppc64', 'ppc'] |
| 11 | pub const valid_comptime_if_cpu_features = ['x64', 'x32', 'little_endian', 'big_endian'] |
| 12 | pub const valid_comptime_if_other = ['apk', 'js', 'debug', 'prod', 'test', 'glibc', 'prealloc', |
| 13 | 'no_bounds_checking', 'freestanding', 'threads', 'js_node', 'js_browser', 'js_freestanding', |
| 14 | 'interpreter', 'es5', 'profile', 'wasm32', 'wasm32_wasi', 'fast_math', 'autofree'] |
| 15 | pub const valid_comptime_not_user_defined = all_valid_comptime_idents() |
| 16 | pub const valid_comptime_compression_types = ['none', 'zlib'] |
| 17 | |
| 18 | fn all_valid_comptime_idents() []string { |
| 19 | mut res := []string{} |
| 20 | res << valid_comptime_if_os |
| 21 | res << valid_comptime_if_compilers |
| 22 | res << valid_comptime_if_platforms |
| 23 | res << valid_comptime_if_cpu_features |
| 24 | res << valid_comptime_if_other |
| 25 | return res |
| 26 | } |
| 27 | |
| 28 | pub fn eval_comptime_not_user_defined_ident(ident string, the_pref &pref.Preferences) !bool { |
| 29 | mut is_true := false |
| 30 | if ident in valid_comptime_if_os { |
| 31 | // `$if bsd` is a family predicate matching any BSD-family target |
| 32 | // (macos, freebsd, openbsd, netbsd, dragonfly), not a specific OS. |
| 33 | if ident == 'bsd' { |
| 34 | is_true = the_pref.os in [.macos, .freebsd, .openbsd, .netbsd, .dragonfly] |
| 35 | } else if ident_enum_val := pref.os_from_string(ident) { |
| 36 | if ident_enum_val == the_pref.os { |
| 37 | is_true = true |
| 38 | } |
| 39 | } |
| 40 | } else if ident in valid_comptime_if_compilers { |
| 41 | is_true = pref.cc_from_string(ident) == the_pref.ccompiler_type |
| 42 | } else if ident in valid_comptime_if_platforms { |
| 43 | match ident { |
| 44 | 'amd64' { |
| 45 | is_true = the_pref.arch == .amd64 |
| 46 | } |
| 47 | 'i386' { |
| 48 | is_true = the_pref.arch == .i386 |
| 49 | } |
| 50 | 'aarch64' { |
| 51 | is_true = the_pref.arch == .arm64 |
| 52 | } |
| 53 | 'arm64' { |
| 54 | is_true = the_pref.arch == .arm64 |
| 55 | } |
| 56 | 'arm32' { |
| 57 | is_true = the_pref.arch == .arm32 |
| 58 | } |
| 59 | 'rv64' { |
| 60 | is_true = the_pref.arch == .rv64 |
| 61 | } |
| 62 | 'rv32' { |
| 63 | is_true = the_pref.arch == .rv32 |
| 64 | } |
| 65 | 's390x' { |
| 66 | is_true = the_pref.arch == .s390x |
| 67 | } |
| 68 | 'ppc64le' { |
| 69 | is_true = the_pref.arch == .ppc64le |
| 70 | } |
| 71 | 'loongarch64' { |
| 72 | is_true = the_pref.arch == .loongarch64 |
| 73 | } |
| 74 | 'sparc64' { |
| 75 | is_true = the_pref.arch == .sparc64 |
| 76 | } |
| 77 | 'ppc64' { |
| 78 | is_true = the_pref.arch == .ppc64 |
| 79 | } |
| 80 | 'ppc' { |
| 81 | is_true = the_pref.arch == .ppc |
| 82 | } |
| 83 | else { |
| 84 | return error('invalid \$if condition: unknown platforms `${ident}`') |
| 85 | } |
| 86 | } |
| 87 | } else if ident in valid_comptime_if_cpu_features { |
| 88 | match ident { |
| 89 | 'x64' { |
| 90 | is_true = the_pref.m64 |
| 91 | } |
| 92 | 'x32' { |
| 93 | is_true = !the_pref.m64 |
| 94 | } |
| 95 | 'little_endian' { |
| 96 | // ppc64le is little-endian (the 'le' suffix), all others below are big-endian |
| 97 | is_true = the_pref.arch !in [.ppc64, .ppc, .sparc64, .s390x] |
| 98 | } |
| 99 | 'big_endian' { |
| 100 | is_true = the_pref.arch in [.ppc64, .ppc, .sparc64, .s390x] |
| 101 | } |
| 102 | else { |
| 103 | return error('invalid \$if condition: unknown cpu_features `${ident}`') |
| 104 | } |
| 105 | } |
| 106 | } else if ident in valid_comptime_if_other { |
| 107 | match ident { |
| 108 | 'apk' { |
| 109 | is_true = the_pref.is_apk |
| 110 | } |
| 111 | 'js' { |
| 112 | is_true = the_pref.backend.is_js() |
| 113 | } |
| 114 | 'debug' { |
| 115 | is_true = the_pref.is_debug |
| 116 | } |
| 117 | 'prod' { |
| 118 | is_true = the_pref.is_prod |
| 119 | } |
| 120 | 'test' { |
| 121 | is_true = the_pref.is_test |
| 122 | } |
| 123 | 'glibc' { |
| 124 | is_true = the_pref.is_glibc |
| 125 | } |
| 126 | 'prealloc' { |
| 127 | is_true = the_pref.prealloc |
| 128 | } |
| 129 | 'no_bounds_checking' { |
| 130 | is_true = the_pref.no_bounds_checking |
| 131 | } |
| 132 | 'freestanding' { |
| 133 | is_true = the_pref.is_bare && !the_pref.output_cross_c |
| 134 | } |
| 135 | 'threads' { |
| 136 | return error('threads should handle outside of `check_valid_ident()`') |
| 137 | } |
| 138 | 'js_node' { |
| 139 | is_true = the_pref.backend == .js_node |
| 140 | } |
| 141 | 'js_browser' { |
| 142 | is_true = the_pref.backend == .js_browser |
| 143 | } |
| 144 | 'js_freestanding' { |
| 145 | is_true = the_pref.backend == .js_freestanding |
| 146 | } |
| 147 | 'interpreter' { |
| 148 | is_true = the_pref.backend == .interpret |
| 149 | } |
| 150 | 'es5' { |
| 151 | is_true = the_pref.output_es5 |
| 152 | } |
| 153 | 'profile' { |
| 154 | is_true = the_pref.is_prof |
| 155 | } |
| 156 | 'wasm32' { |
| 157 | is_true = the_pref.arch == .wasm32 |
| 158 | } |
| 159 | 'wasm32_wasi' { |
| 160 | is_true = the_pref.os == .wasm32_wasi |
| 161 | } |
| 162 | 'fast_math' { |
| 163 | is_true = the_pref.fast_math |
| 164 | } |
| 165 | 'autofree' { |
| 166 | is_true = the_pref.autofree |
| 167 | } |
| 168 | else { |
| 169 | return error('invalid \$if condition: unknown other indent `${ident}`') |
| 170 | } |
| 171 | } |
| 172 | } else if ident in the_pref.compile_defines { |
| 173 | is_true = true |
| 174 | } else { |
| 175 | return error('invalid \$if condition: unknown indent `${ident}`') |
| 176 | } |
| 177 | return is_true |
| 178 | } |
| 179 | |
| 180 | pub const system_ident_map = { |
| 181 | // OS |
| 182 | 'windows': '_WIN32' |
| 183 | 'ios': '__TARGET_IOS__' |
| 184 | 'macos': '__APPLE__' |
| 185 | 'mac': '__APPLE__' |
| 186 | 'mach': '__MACH__' |
| 187 | 'darwin': '__DARWIN__' |
| 188 | 'hpux': '__HPUX__' |
| 189 | 'gnu': '__GNU__' |
| 190 | 'qnx': '__QNX__' |
| 191 | 'linux': '__linux__' |
| 192 | 'serenity': '__serenity__' |
| 193 | 'plan9': '__plan9__' |
| 194 | 'vinix': '__vinix__' |
| 195 | 'freebsd': '__FreeBSD__' |
| 196 | 'openbsd': '__OpenBSD__' |
| 197 | 'netbsd': '__NetBSD__' |
| 198 | 'bsd': '__BSD__' |
| 199 | 'dragonfly': '__DragonFly__' |
| 200 | 'android': '__ANDROID__' |
| 201 | 'termux': '__TERMUX__' |
| 202 | 'solaris': '__sun' |
| 203 | 'haiku': '__HAIKU__' |
| 204 | // Backend |
| 205 | 'js': '_VJS' |
| 206 | 'wasm32_emscripten': '__EMSCRIPTEN__' |
| 207 | // Compiler |
| 208 | 'gcc': '__V_GCC__' |
| 209 | 'tinyc': '__TINYC__' |
| 210 | 'clang': '__clang__' |
| 211 | 'mingw': '__MINGW32__' |
| 212 | 'msvc': '_MSC_VER' |
| 213 | 'cplusplus': '__cplusplus' |
| 214 | // Others |
| 215 | 'threads': '__VTHREADS__' |
| 216 | 'gcboehm': '_VGCBOEHM' |
| 217 | 'debug': '_VDEBUG' |
| 218 | 'prod': '_VPROD' |
| 219 | 'profile': '_VPROFILE' |
| 220 | 'test': '_VTEST' |
| 221 | 'glibc': '__GLIBC__' |
| 222 | 'prealloc': '_VPREALLOC' |
| 223 | 'no_bounds_checking': 'CUSTOM_DEFINE_no_bounds_checking' |
| 224 | 'freestanding': '_VFREESTANDING' |
| 225 | 'autofree': '_VAUTOFREE' |
| 226 | // CPU |
| 227 | 'amd64': '__V_amd64' |
| 228 | 'aarch64': '__V_arm64' |
| 229 | 'arm64': '__V_arm64' // aarch64 alias |
| 230 | 'arm32': '__V_arm32' |
| 231 | 'i386': '__V_x86' |
| 232 | 'rv64': '__V_rv64' |
| 233 | 'riscv64': '__V_rv64' // rv64 alias |
| 234 | 'rv32': '__V_rv32' |
| 235 | 'riscv32': '__V_rv32' // rv32 alias |
| 236 | 's390x': '__V_s390x' |
| 237 | 'ppc64le': '__V_ppc64le' |
| 238 | 'loongarch64': '__V_loongarch64' |
| 239 | 'sparc64': '__V_sparc64' |
| 240 | 'ppc': '__V_ppc' |
| 241 | 'x64': 'TARGET_IS_64BIT' |
| 242 | 'x32': 'TARGET_IS_32BIT' |
| 243 | 'little_endian': 'TARGET_ORDER_IS_LITTLE' |
| 244 | 'big_endian': 'TARGET_ORDER_IS_BIG' |
| 245 | } |
| 246 | |
| 247 | pub fn comptime_if_to_ifdef(name string, the_pref &pref.Preferences) !string { |
| 248 | if name == 'fast_math' { |
| 249 | return if the_pref.ccompiler_type == .msvc { |
| 250 | // turned on by: `-cflags /fp:fast` |
| 251 | '_M_FP_FAST' |
| 252 | } else { |
| 253 | // turned on by: `-cflags -ffast-math` |
| 254 | '__FAST_MATH__' |
| 255 | } |
| 256 | } |
| 257 | if ifdef := system_ident_map[name] { |
| 258 | return ifdef |
| 259 | } |
| 260 | return error('bad os ifdef name `${name}`') |
| 261 | } |
| 262 | |