// Copyright (c) 2023 l-m.dev. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module wasm import v.ast pub fn (mut g Gen) comptime_cond(cond ast.Expr) bool { match cond { ast.BoolLiteral { return cond.val } ast.ParExpr { g.comptime_cond(cond.expr) } ast.PrefixExpr { if cond.op == .not { return !g.comptime_cond(cond.right) } } ast.InfixExpr { match cond.op { .and { return g.comptime_cond(cond.left) && g.comptime_cond(cond.right) } .logical_or { return g.comptime_cond(cond.left) || g.comptime_cond(cond.right) } .eq { return g.comptime_cond(cond.left) == g.comptime_cond(cond.right) } .ne { return g.comptime_cond(cond.left) != g.comptime_cond(cond.right) } // wasm doesn't support generics // .key_is, .not_is else {} } } ast.Ident { return g.comptime_if_to_ifdef(cond.name, false) } ast.ComptimeCall { return false // pkg_exists, more documentation needed here... } ast.PostfixExpr { return g.comptime_if_to_ifdef((cond.expr as ast.Ident).name, true) } else {} } g.w_error('wasm.comptime_cond(): unhandled node: ' + cond.type_name()) } pub fn (mut g Gen) comptime_if_expr(node ast.IfExpr, expected ast.Type, existing_rvars []Var) { if !node.is_expr && !node.has_else && node.branches.len == 1 { if node.branches[0].stmts.len == 0 { // empty ifdef; result of target OS != conditional => skip return } } for i, branch in node.branches { has_expr := !(node.has_else && i + 1 >= node.branches.len) if has_expr && !g.comptime_cond(branch.cond) { continue } // !node.is_expr || cond // handles else case, and if cond is true g.rvar_expr_stmts(branch.stmts, expected, existing_rvars) break } } pub fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) bool { match name { // platforms/os-es/compilers: 'windows', 'ios', 'macos', 'mach', 'darwin', 'linux', 'freebsd', 'openbsd', 'bsd', 'android', 'solaris', 'js_node', 'js_freestanding', 'js_browser', 'es5', 'js', 'native', 'glibc', 'gcc', 'tinyc', 'clang', 'mingw', 'msvc', 'cplusplus', 'gcboehm', 'prealloc', 'freestanding', 'amd64', 'aarch64', 'arm64' { return false } 'wasm' { return true } // 'debug' { return g.pref.is_debug } 'prod' { return g.pref.is_prod } // wasm doesn't support testing 'test' { return false } // wasm doesn't support threads 'threads' { return false } 'no_bounds_checking' { return g.pref.no_bounds_checking } // bitness: 'x64' { return false } 'x32' { return true } // endianness: 'little_endian' { return true } 'big_endian' { return false } else { // note: this works but there might be some things missing from what I saw in the other platforms // but it is better than nothing if name in g.pref.compile_defines { return true } else { return false } // taken from JS: what does it do?? /* if is_comptime_option || (g.pref.compile_defines_all.len > 0 && name in g.pref.compile_defines_all) { return 'checkDefine("CUSTOM_DEFINE_${name}")' } return error('bad os ifdef name "${name}"') */ } } g.w_error('wasm.comptime_if_to_ifdef(): unhandled `${name}`, is_comptime_option: ${is_comptime_option}') }