v2 / vlib / v / gen / wasm / comptime.v
141 lines · 132 sloc · 3.31 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
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.
4module wasm
5
6import v.ast
7
8pub 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
55pub 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
76pub 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