v2 / vlib / v / comptime / comptime.v
512 lines · 486 sloc · 12.22 KB · a75b9622292f36a85c5da0926c1f8a1e1623e4ae
Raw
1module comptime
2
3import v.pref
4import v.ast
5
6pub struct Comptime {
7 pref &pref.Preferences
8pub mut:
9 table &ast.Table = unsafe { nil }
10 file &ast.File = unsafe { nil }
11}
12
13pub fn new_comptime(pref_ &pref.Preferences) &Comptime {
14 return &Comptime{
15 pref: pref_
16 }
17}
18
19pub fn new_comptime_with_table(table &ast.Table, pref_ &pref.Preferences) &Comptime {
20 mut c := new_comptime(pref_)
21 c.table = table
22 return c
23}
24
25pub fn (mut c Comptime) solve_files(ast_files []&ast.File) {
26 for i in 0 .. ast_files.len {
27 mut file := unsafe { ast_files[i] }
28 c.solve(mut file)
29 }
30}
31
32pub fn (mut c Comptime) solve(mut ast_file ast.File) {
33 c.file = ast_file
34 ast_file.stmts = c.stmts(mut ast_file.stmts)
35}
36
37pub fn (mut c Comptime) stmts(mut nodes []ast.Stmt) []ast.Stmt {
38 for mut stmt in nodes {
39 stmt = c.stmt(mut stmt)
40 }
41 return nodes
42}
43
44pub fn (mut c Comptime) stmt(mut node ast.Stmt) ast.Stmt {
45 match mut node {
46 ast.EmptyStmt {}
47 ast.NodeError {}
48 ast.AsmStmt {}
49 ast.DebuggerStmt {}
50 ast.AssertStmt {
51 node.expr = c.expr(mut node.expr)
52 }
53 ast.AssignStmt {
54 node.right = c.exprs(mut node.right)
55 node.left = c.exprs(mut node.left)
56 }
57 ast.Block {
58 node.stmts = c.stmts(mut node.stmts)
59 }
60 ast.BranchStmt {}
61 ast.ComptimeFor {
62 node.stmts = c.stmts(mut node.stmts)
63 }
64 ast.ConstDecl {
65 // node.fields = c.const_decl_fields(mut node.fields)
66 }
67 ast.DeferStmt {
68 node.stmts = c.stmts(mut node.stmts)
69 }
70 ast.EnumDecl {
71 // node.fields = c.enum_decl_fields(mut node.fields)
72 }
73 ast.ExprStmt {
74 res := c.expr_stmt(mut node.expr)
75 match res {
76 ast.Expr {
77 node.expr = res
78 }
79 ast.Stmt {
80 return res
81 }
82 }
83 }
84 ast.FnDecl {
85 node.stmts = c.stmts(mut node.stmts)
86 }
87 ast.ForCStmt {
88 if node.has_init && !node.is_multi {
89 node.init = c.stmt(mut node.init)
90 }
91
92 if node.has_cond {
93 node.cond = c.expr(mut node.cond)
94 }
95
96 node.stmts = c.stmts(mut node.stmts)
97
98 if node.has_inc && !node.is_multi {
99 node.inc = c.stmt(mut node.inc)
100 }
101 }
102 ast.ForInStmt {
103 node.stmts = c.stmts(mut node.stmts)
104 }
105 ast.ForStmt {
106 node.cond = c.expr(mut node.cond)
107 node.stmts = c.stmts(mut node.stmts)
108 }
109 ast.GlobalDecl {
110 // node.fields = c.global_decl_fields(mut node.fields)
111 }
112 ast.GotoLabel {}
113 ast.GotoStmt {}
114 ast.HashStmt {
115 // node.ct.conds = c.hashstmt_ct_conds(mut node.ct_conds)
116 }
117 ast.Import {}
118 ast.InterfaceDecl {
119 // node.fields = c.interface_decl_fields(mut node.fields)
120 }
121 ast.Module {}
122 ast.Return {
123 node.exprs = c.exprs(mut node.exprs)
124 }
125 ast.SemicolonStmt {}
126 ast.SqlStmt {}
127 ast.StructDecl {
128 // node.fields = c.struct_decl_fields(mut node.fields)
129 }
130 ast.TypeDecl {}
131 }
132
133 return node
134}
135
136type StmtOrExpr = ast.Expr | ast.Stmt
137
138pub fn (mut c Comptime) check_type_equality(left_type ast.Type, right ast.Expr) !bool {
139 if right is ast.ComptimeType {
140 if right.kind == .array {
141 return c.table.sym(left_type).info is ast.Array
142 || c.table.sym(left_type).info is ast.ArrayFixed
143 } else if right.kind == .array_dynamic {
144 return c.table.sym(left_type).info is ast.Array
145 } else if right.kind == .array_fixed {
146 return c.table.sym(left_type).info is ast.ArrayFixed
147 } else if right.kind == .iface {
148 return c.table.sym(left_type).info is ast.Interface
149 } else if right.kind == .map {
150 return c.table.sym(left_type).info is ast.Map
151 } else if right.kind == .struct {
152 return c.table.sym(left_type).info is ast.Struct
153 } else if right.kind == .enum {
154 return c.table.sym(left_type).info is ast.Enum
155 } else if right.kind == .sum_type {
156 return c.table.sym(left_type).info is ast.SumType
157 } else if right.kind == .alias {
158 return c.table.sym(left_type).info is ast.Alias
159 } else if right.kind == .int {
160 return left_type.is_int()
161 } else if right.kind == .string {
162 return left_type.is_string()
163 } else if right.kind == .float {
164 return left_type.is_float()
165 }
166 // TODO do the other types
167 } else if right is ast.TypeNode {
168 sym := c.table.sym(right.typ)
169 if sym.info is ast.Interface {
170 return c.table.does_type_implement_interface(left_type, right.typ)
171 } else {
172 return left_type == right.typ
173 }
174 }
175 return error('Cannot solve')
176}
177
178pub fn (mut c Comptime) is_true(expr ast.Expr) !bool {
179 match expr {
180 ast.InfixExpr {
181 match expr.op {
182 .key_is {
183 if expr.left is ast.TypeNode {
184 return c.check_type_equality(expr.left.typ, expr.right)!
185 } else if expr.left is ast.SelectorExpr {
186 if expr.left.field_name == 'typ' && expr.left.expr is ast.Ident {
187 ident_typ := match expr.left.expr.info {
188 ast.IdentFn { expr.left.expr.info.typ }
189 ast.IdentVar { expr.left.expr.info.typ }
190 }
191
192 if ident_typ != ast.no_type {
193 return c.check_type_equality(ident_typ, expr.right)!
194 }
195 } else if expr.left.field_name == 'unaliased_typ' {
196 if expr.left.expr is ast.Ident {
197 unaliased_type := c.table.unaliased_type(expr.left.expr.obj.typ)
198 return c.check_type_equality(unaliased_type, expr.right)!
199 }
200 }
201 } else if expr.left is ast.Ident {
202 return c.check_type_equality(expr.left.obj.typ, expr.right)!
203 }
204 }
205 .and {
206 left := c.is_true(expr.left)!
207 right := c.is_true(expr.right)!
208 return left && right
209 }
210 .logical_or {
211 left := c.is_true(expr.left)!
212 right := c.is_true(expr.right)!
213 return left || right
214 }
215 else {}
216 }
217 }
218 ast.NodeError {
219 // else
220 return true
221 }
222 else {}
223 }
224
225 return error('Cannot solve')
226}
227
228pub fn if_branch_to_block(b ast.IfBranch) ast.Block {
229 return ast.Block{
230 stmts: b.stmts
231 scope: b.scope
232 }
233}
234
235pub fn (mut c Comptime) expr_stmt(mut node ast.Expr) StmtOrExpr {
236 match mut node {
237 ast.IfExpr {
238 if node.is_comptime {
239 if !node.is_expr && !node.has_else && node.branches.len == 1 {
240 if node.branches[0].stmts.len == 0 {
241 // empty ifdef; result of target OS != conditional => skip
242 return ast.Stmt(ast.EmptyStmt{
243 pos: node.pos
244 })
245 }
246 if !c.pref.output_cross_c {
247 if node.branches[0].cond is ast.Ident {
248 if c.pref.os == (pref.os_from_string(node.branches[0].cond.name) or {
249 pref.OS._auto
250 }) {
251 // Same target OS as the conditional...
252 // => skip the #if defined ... #endif wrapper
253 // and just generate the branch statements:
254 node.branches[0].stmts = c.stmts(mut node.branches[0].stmts)
255 return ast.Stmt(if_branch_to_block(node.branches[0]))
256 }
257 }
258 }
259 }
260 if c.pref.new_generic_solver {
261 mut has_true_branch := false
262 mut cant_solve := false
263 for mut b in node.branches {
264 if c.is_true(b.cond) or {
265 cant_solve = true
266 break
267 }
268 {
269 has_true_branch = true
270 if node.is_expr {
271 // TODO
272 } else {
273 b.stmts = c.stmts(mut b.stmts)
274 return ast.Stmt(if_branch_to_block(b))
275 }
276 }
277 }
278 if !cant_solve && !has_true_branch {
279 return ast.Stmt(ast.EmptyStmt{
280 pos: node.pos
281 })
282 }
283 }
284 }
285 return c.expr(mut node)
286 }
287 else {
288 return c.expr(mut node)
289 }
290 }
291
292 return node
293}
294
295pub fn (mut c Comptime) exprs(mut nodes []ast.Expr) []ast.Expr {
296 for mut e in nodes {
297 e = c.expr(mut e)
298 }
299 return nodes
300}
301
302pub fn (mut c Comptime) expr(mut node ast.Expr) ast.Expr {
303 match mut node {
304 ast.AnonFn {
305 node.decl = c.stmt(mut node.decl) as ast.FnDecl
306 }
307 ast.ArrayDecompose {
308 node.expr = c.expr(mut node.expr)
309 }
310 ast.ArrayInit {
311 node.exprs = c.exprs(mut node.exprs)
312 if node.has_len {
313 node.len_expr = c.expr(mut node.len_expr)
314 }
315 if node.has_cap {
316 node.cap_expr = c.expr(mut node.cap_expr)
317 }
318 if node.has_init {
319 node.init_expr = c.expr(mut node.init_expr)
320 }
321 }
322 ast.AsCast {
323 node.expr = c.expr(mut node.expr)
324 }
325 ast.CTempVar {
326 node.orig = c.expr(mut node.orig)
327 }
328 ast.CallExpr {
329 node.left = c.expr(mut node.left)
330 for mut arg in node.args {
331 arg.expr = c.expr(mut arg.expr)
332 }
333 node.or_block = c.expr(mut node.or_block) as ast.OrExpr
334 }
335 ast.CastExpr {
336 node.arg = c.expr(mut node.arg)
337 node.expr = c.expr(mut node.expr)
338 }
339 ast.ChanInit {
340 node.cap_expr = c.expr(mut node.cap_expr)
341 }
342 ast.ComptimeCall {
343 for mut arg in node.args {
344 arg.expr = c.expr(mut arg.expr)
345 }
346 }
347 ast.ComptimeSelector {
348 node.left = c.expr(mut node.left)
349 node.field_expr = c.expr(mut node.field_expr)
350 }
351 ast.ConcatExpr {
352 for mut val in node.vals {
353 val = c.expr(mut val)
354 }
355 }
356 ast.DumpExpr {
357 node.expr = c.expr(mut node.expr)
358 }
359 ast.GoExpr {
360 node.call_expr = c.expr(mut node.call_expr) as ast.CallExpr
361 }
362 ast.IfExpr {
363 for mut branch in node.branches {
364 branch.cond = c.expr(mut branch.cond)
365 branch.stmts = c.stmts(mut branch.stmts)
366 }
367 // where we place the result of the if when a := if ...
368 node.left = c.expr(mut node.left)
369 }
370 ast.IfGuardExpr {
371 node.expr = c.expr(mut node.expr)
372 }
373 ast.IndexExpr {
374 node.left = c.expr(mut node.left)
375 node.index = c.expr(mut node.index)
376 mut indices := []ast.Expr{cap: node.indices.len}
377 for mut index in node.indices {
378 indices << c.expr(mut index)
379 }
380 node.indices = indices
381 node.or_expr = c.expr(mut node.or_expr) as ast.OrExpr
382 }
383 ast.InfixExpr {
384 node.left = c.expr(mut node.left)
385 node.right = c.expr(mut node.right)
386 }
387 ast.IsRefType {
388 node.expr = c.expr(mut node.expr)
389 }
390 ast.Likely {
391 node.expr = c.expr(mut node.expr)
392 }
393 ast.LockExpr {
394 node.stmts = c.stmts(mut node.stmts)
395 node.lockeds = c.exprs(mut node.lockeds)
396 }
397 ast.MapInit {
398 node.keys = c.exprs(mut node.keys)
399 node.vals = c.exprs(mut node.vals)
400 }
401 ast.MatchExpr {
402 node.cond = c.expr(mut node.cond)
403 for mut branch in node.branches {
404 branch.exprs = c.exprs(mut branch.exprs)
405 branch.stmts = c.stmts(mut branch.stmts)
406 }
407 }
408 ast.OrExpr {
409 node.stmts = c.stmts(mut node.stmts)
410 }
411 ast.ParExpr {
412 node.expr = c.expr(mut node.expr)
413 }
414 ast.PostfixExpr {
415 node.expr = c.expr(mut node.expr)
416 }
417 ast.PrefixExpr {
418 node.right = c.expr(mut node.right)
419 node.or_block = c.expr(mut node.or_block) as ast.OrExpr
420 }
421 ast.RangeExpr {
422 node.low = c.expr(mut node.low)
423 node.high = c.expr(mut node.high)
424 }
425 ast.SelectExpr {
426 for mut branch in node.branches {
427 branch.stmt = c.stmt(mut branch.stmt)
428 branch.stmts = c.stmts(mut branch.stmts)
429 }
430 }
431 ast.SelectorExpr {
432 if c.pref.new_generic_solver && node.gkind_field == .name && node.field_name == 'name' {
433 if mut node.expr is ast.Ident {
434 return ast.Expr(ast.StringLiteral{
435 val: node.expr.name
436 pos: node.pos
437 })
438 }
439 }
440 node.expr = c.expr(mut node.expr)
441 }
442 ast.SizeOf {
443 node.expr = c.expr(mut node.expr)
444 }
445 ast.SqlExpr {
446 node.db_expr = c.expr(mut node.db_expr)
447 if node.has_where {
448 node.where_expr = c.expr(mut node.where_expr)
449 }
450 if node.has_order {
451 node.order_expr = c.expr(mut node.order_expr)
452 }
453 if node.has_limit {
454 node.limit_expr = c.expr(mut node.limit_expr)
455 }
456 if node.has_offset {
457 node.offset_expr = c.expr(mut node.offset_expr)
458 }
459 for mut field in node.fields {
460 field.default_expr = c.expr(mut field.default_expr)
461 }
462 for _, mut sub_struct in node.sub_structs {
463 sub_struct = c.expr(mut sub_struct) as ast.SqlExpr
464 }
465 }
466 ast.SqlQueryDataExpr {
467 node.items = c.sql_query_data_items(node.items)
468 }
469 ast.StringInterLiteral {
470 node.exprs = c.exprs(mut node.exprs)
471 node.fwidth_exprs = c.exprs(mut node.fwidth_exprs)
472 node.precision_exprs = c.exprs(mut node.precision_exprs)
473 }
474 ast.StructInit {
475 node.update_expr = c.expr(mut node.update_expr)
476 for mut init_field in node.init_fields {
477 init_field.expr = c.expr(mut init_field.expr)
478 }
479 }
480 ast.UnsafeExpr {
481 node.expr = c.expr(mut node.expr)
482 }
483 else {}
484 }
485
486 return node
487}
488
489fn (mut c Comptime) sql_query_data_items(items []ast.SqlQueryDataItem) []ast.SqlQueryDataItem {
490 mut new_items := []ast.SqlQueryDataItem{cap: items.len}
491 for item in items {
492 mut item_copy := item
493 new_items << c.sql_query_data_item(mut item_copy)
494 }
495 return new_items
496}
497
498fn (mut c Comptime) sql_query_data_item(mut item ast.SqlQueryDataItem) ast.SqlQueryDataItem {
499 match mut item {
500 ast.SqlQueryDataLeaf {
501 item.expr = c.expr(mut item.expr)
502 }
503 ast.SqlQueryDataIf {
504 for mut branch in item.branches {
505 branch.cond = c.expr(mut branch.cond)
506 branch.items = c.sql_query_data_items(branch.items)
507 }
508 }
509 }
510
511 return item
512}
513