| 1 | // Copyright (c) 2023 l-m.dev. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | module wasm |
| 5 | |
| 6 | import v.ast |
| 7 | |
| 8 | pub fn (mut g Gen) comptime_cond(cond ast.Expr) bool { |
| 9 | match cond { |
| 10 | ast.BoolLiteral { |
| 11 | return cond.val |
| 12 | } |
| 13 | ast.ParExpr { |
| 14 | g.comptime_cond(cond.expr) |
| 15 | } |
| 16 | ast.PrefixExpr { |
| 17 | if cond.op == .not { |
| 18 | return !g.comptime_cond(cond.right) |
| 19 | } |
| 20 | } |
| 21 | ast.InfixExpr { |
| 22 | match cond.op { |
| 23 | .and { |
| 24 | return g.comptime_cond(cond.left) && g.comptime_cond(cond.right) |
| 25 | } |
| 26 | .logical_or { |
| 27 | return g.comptime_cond(cond.left) || g.comptime_cond(cond.right) |
| 28 | } |
| 29 | .eq { |
| 30 | return g.comptime_cond(cond.left) == g.comptime_cond(cond.right) |
| 31 | } |
| 32 | .ne { |
| 33 | return g.comptime_cond(cond.left) != g.comptime_cond(cond.right) |
| 34 | } |
| 35 | // wasm doesn't support generics |
| 36 | // .key_is, .not_is |
| 37 | else {} |
| 38 | } |
| 39 | } |
| 40 | ast.Ident { |
| 41 | return g.comptime_if_to_ifdef(cond.name, false) |
| 42 | } |
| 43 | ast.ComptimeCall { |
| 44 | return false // pkg_exists, more documentation needed here... |
| 45 | } |
| 46 | ast.PostfixExpr { |
| 47 | return g.comptime_if_to_ifdef((cond.expr as ast.Ident).name, true) |
| 48 | } |
| 49 | else {} |
| 50 | } |
| 51 | |
| 52 | g.w_error('wasm.comptime_cond(): unhandled node: ' + cond.type_name()) |
| 53 | } |
| 54 | |
| 55 | pub fn (mut g Gen) comptime_if_expr(node ast.IfExpr, expected ast.Type, existing_rvars []Var) { |
| 56 | if !node.is_expr && !node.has_else && node.branches.len == 1 { |
| 57 | if node.branches[0].stmts.len == 0 { |
| 58 | // empty ifdef; result of target OS != conditional => skip |
| 59 | return |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | for i, branch in node.branches { |
| 64 | has_expr := !(node.has_else && i + 1 >= node.branches.len) |
| 65 | |
| 66 | if has_expr && !g.comptime_cond(branch.cond) { |
| 67 | continue |
| 68 | } |
| 69 | // !node.is_expr || cond |
| 70 | // handles else case, and if cond is true |
| 71 | g.rvar_expr_stmts(branch.stmts, expected, existing_rvars) |
| 72 | break |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | pub fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) bool { |
| 77 | match name { |
| 78 | // platforms/os-es/compilers: |
| 79 | 'windows', 'ios', 'macos', 'mach', 'darwin', 'linux', 'freebsd', 'openbsd', 'bsd', |
| 80 | 'android', 'solaris', 'js_node', 'js_freestanding', 'js_browser', 'es5', 'js', 'native', |
| 81 | 'glibc', 'gcc', 'tinyc', 'clang', 'mingw', 'msvc', 'cplusplus', 'gcboehm', 'prealloc', |
| 82 | 'freestanding', 'amd64', 'aarch64', 'arm64' { |
| 83 | return false |
| 84 | } |
| 85 | 'wasm' { |
| 86 | return true |
| 87 | } |
| 88 | // |
| 89 | 'debug' { |
| 90 | return g.pref.is_debug |
| 91 | } |
| 92 | 'prod' { |
| 93 | return g.pref.is_prod |
| 94 | } |
| 95 | // wasm doesn't support testing |
| 96 | 'test' { |
| 97 | return false |
| 98 | } |
| 99 | // wasm doesn't support threads |
| 100 | 'threads' { |
| 101 | return false |
| 102 | } |
| 103 | 'no_bounds_checking' { |
| 104 | return g.pref.no_bounds_checking |
| 105 | } |
| 106 | // bitness: |
| 107 | 'x64' { |
| 108 | return false |
| 109 | } |
| 110 | 'x32' { |
| 111 | return true |
| 112 | } |
| 113 | // endianness: |
| 114 | 'little_endian' { |
| 115 | return true |
| 116 | } |
| 117 | 'big_endian' { |
| 118 | return false |
| 119 | } |
| 120 | else { |
| 121 | // note: this works but there might be some things missing from what I saw in the other platforms |
| 122 | // but it is better than nothing |
| 123 | if name in g.pref.compile_defines { |
| 124 | return true |
| 125 | } else { |
| 126 | return false |
| 127 | } |
| 128 | |
| 129 | // taken from JS: what does it do?? |
| 130 | /* |
| 131 | if is_comptime_option |
| 132 | || (g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all) { |
| 133 | return 'checkDefine("CUSTOM_DEFINE_${name}")' |
| 134 | } |
| 135 | return error('bad os ifdef name "${name}"') |
| 136 | */ |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | g.w_error('wasm.comptime_if_to_ifdef(): unhandled `${name}`, is_comptime_option: ${is_comptime_option}') |
| 141 | } |
| 142 | |