v2 / vlib / v / generics / generics.v
1379 lines · 1341 sloc · 38.19 KB · a75b9622292f36a85c5da0926c1f8a1e1623e4ae
Raw
1module generics
2
3// TODO do scopes need to be cloned?
4import v.pref
5import v.ast
6import strings
7
8// Stage for solving generics
9
10const result_name = ast.result_name
11const option_name = ast.option_name
12
13pub struct Generics {
14 pref &pref.Preferences
15pub mut:
16 table &ast.Table = unsafe { nil }
17 file &ast.File = unsafe { nil }
18 styp_cache map[ast.Type]string
19 cur_fn &ast.FnDecl = unsafe { nil }
20 cur_concrete_types []ast.Type
21 inside_struct_init bool
22 cur_struct_init_node &ast.StructInit = unsafe { nil }
23 forin_types map[string]ast.Type // maps the name of the elem variable (`for elem in my_array`) to the solved type
24}
25
26pub fn new_generics(pref_ &pref.Preferences) &Generics {
27 return &Generics{
28 pref: pref_
29 }
30}
31
32pub fn new_generics_with_table(table &ast.Table, pref_ &pref.Preferences) &Generics {
33 mut g := new_generics(pref_)
34 g.table = table
35 return g
36}
37
38pub fn (mut g Generics) solve_files(ast_files []&ast.File) {
39 for i in 0 .. ast_files.len {
40 mut file := unsafe { ast_files[i] }
41 g.solve(mut file)
42 }
43}
44
45pub fn (mut g Generics) solve(mut ast_file ast.File) {
46 g.file = ast_file
47 ast_file.stmts = g.stmts(mut ast_file.stmts)
48}
49
50pub fn (mut g Generics) stmts(mut nodes []ast.Stmt) []ast.Stmt {
51 mut solved_indexes := []int{}
52 mut solved_generic_fns := []ast.Stmt{}
53 for i, mut stmt in nodes {
54 match mut stmt {
55 ast.FnDecl {
56 old_cur_fn := g.cur_fn
57 g.cur_fn = unsafe { &stmt }
58 if stmt.generic_names.len > 0 {
59 solved_generic_fns << g.generic_fn_decl(mut stmt)
60 solved_indexes << i
61 } else {
62 nodes[i] = g.stmt(mut stmt)
63 }
64 g.cur_fn = old_cur_fn
65 }
66 else {
67 stmt = g.stmt(mut stmt)
68 }
69 }
70 }
71 for idx := solved_indexes.len; idx > 0; idx-- {
72 nodes.delete(solved_indexes[idx - 1])
73 }
74 nodes << solved_generic_fns
75 return nodes
76}
77
78pub fn (mut g Generics) stmt(mut node ast.Stmt) ast.Stmt {
79 match mut node {
80 ast.EmptyStmt {}
81 ast.NodeError {}
82 ast.AsmStmt {}
83 ast.DebuggerStmt {}
84 ast.AssertStmt {
85 if g.cur_concrete_types.len > 0 {
86 return ast.Stmt(ast.AssertStmt{
87 ...node
88 expr: g.expr(mut node.expr)
89 })
90 }
91 node.expr = g.expr(mut node.expr)
92 }
93 ast.AssignStmt {
94 if g.cur_concrete_types.len > 0 {
95 mut right := node.right.clone()
96 mut left := node.left.clone()
97 return ast.Stmt(ast.AssignStmt{
98 ...node
99 right: g.exprs(mut right)
100 left: g.exprs(mut left)
101 left_types: node.left_types.map(g.unwrap_generic(it))
102 right_types: node.right_types.map(g.unwrap_generic(it))
103 })
104 }
105 node.right = g.exprs(mut node.right)
106 node.left = g.exprs(mut node.left)
107 }
108 ast.Block {
109 if g.cur_concrete_types.len > 0 {
110 mut stmts := node.stmts.clone()
111 return ast.Stmt(ast.Block{
112 ...node
113 stmts: g.stmts(mut stmts)
114 })
115 }
116 node.stmts = g.stmts(mut node.stmts)
117 }
118 ast.BranchStmt {}
119 ast.ComptimeFor {
120 if g.cur_concrete_types.len > 0 {
121 mut stmts := node.stmts.clone()
122 return ast.Stmt(ast.ComptimeFor{
123 ...node
124 typ: g.unwrap_generic(node.typ)
125 stmts: g.stmts(mut stmts)
126 })
127 }
128 node.stmts = g.stmts(mut node.stmts)
129 }
130 ast.ConstDecl {
131 if g.cur_concrete_types.len > 0 {
132 mut fields := node.fields.clone()
133 for mut field in fields {
134 field.typ = g.unwrap_generic(field.typ)
135 field.expr = g.expr(mut field.expr)
136 }
137 return ast.Stmt(ast.ConstDecl{
138 ...node
139 fields: fields
140 })
141 }
142 for mut field in node.fields {
143 field.expr = g.expr(mut field.expr)
144 }
145 }
146 ast.DeferStmt {
147 if g.cur_concrete_types.len > 0 {
148 mut stmts := node.stmts.clone()
149 return ast.Stmt(ast.DeferStmt{
150 ...node
151 stmts: g.stmts(mut stmts)
152 })
153 }
154 node.stmts = g.stmts(mut node.stmts)
155 }
156 ast.EnumDecl {}
157 ast.ExprStmt {
158 if g.cur_concrete_types.len > 0 {
159 return ast.Stmt(ast.ExprStmt{
160 ...node
161 expr: g.expr(mut node.expr)
162 typ: g.unwrap_generic(node.typ)
163 })
164 }
165 node.expr = g.expr(mut node.expr)
166 }
167 ast.FnDecl {
168 if g.cur_concrete_types.len > 0 {
169 old_cur_fn := g.cur_fn
170 g.cur_fn = unsafe { &node }
171 mut params := node.params.clone()
172 for mut param in params {
173 param.typ = g.unwrap_generic(param.typ)
174 }
175 mut stmts := node.stmts.clone()
176 stmts = g.stmts(mut stmts)
177 mut defer_stmts := node.defer_stmts.clone()
178 for mut defer_stmt in defer_stmts {
179 defer_stmt = g.stmt(mut defer_stmt) as ast.DeferStmt
180 }
181 g.cur_fn = old_cur_fn
182 return ast.Stmt(ast.FnDecl{
183 ...node
184 receiver: ast.StructField{
185 ...node.receiver
186 typ: g.unwrap_generic(node.receiver.typ)
187 }
188 return_type: g.unwrap_generic(node.return_type)
189 params: params
190 stmts: stmts
191 defer_stmts: defer_stmts
192 })
193 }
194 old_cur_fn := g.cur_fn
195 g.cur_fn = unsafe { &node }
196 node.stmts = g.stmts(mut node.stmts)
197 g.cur_fn = old_cur_fn
198 }
199 ast.ForCStmt {
200 if g.cur_concrete_types.len > 0 {
201 mut stmts := node.stmts.clone()
202 return ast.Stmt(ast.ForCStmt{
203 ...node
204 cond: g.expr(mut node.cond)
205 init: g.stmt(mut node.init)
206 inc: g.stmt(mut node.inc)
207 stmts: g.stmts(mut stmts)
208 })
209 }
210 if node.has_init && !node.is_multi {
211 node.init = g.stmt(mut node.init)
212 }
213
214 if node.has_cond {
215 node.cond = g.expr(mut node.cond)
216 }
217
218 node.stmts = g.stmts(mut node.stmts)
219
220 if node.has_inc && !node.is_multi {
221 node.inc = g.stmt(mut node.inc)
222 }
223 }
224 ast.ForInStmt {
225 if g.cur_concrete_types.len > 0 {
226 mut stmts := node.stmts.clone()
227 if mut node.cond is ast.Ident && node.cond.ct_expr {
228 // Solve the type for elem in `for elem in my_array` when my_array is T
229 unwrapped_typ := g.unwrap_generic(node.cond_type)
230 node.val_type = g.table.value_type(unwrapped_typ)
231 if node.val_is_mut {
232 node.val_type = node.val_type.ref()
233 }
234 g.forin_types[node.val_var] = node.val_type
235 defer(fn) {
236 g.forin_types.delete(node.val_var)
237 }
238 }
239 mut new_node := ast.ForInStmt{
240 ...node
241 cond: g.expr(mut node.cond)
242 high: g.expr(mut node.high)
243 key_type: g.unwrap_generic(node.key_type)
244 val_type: g.unwrap_generic(node.val_type)
245 cond_type: g.unwrap_generic(node.cond_type)
246 high_type: g.unwrap_generic(node.high_type)
247 stmts: g.stmts(mut stmts)
248 }
249 return ast.Stmt(new_node)
250 }
251 node.stmts = g.stmts(mut node.stmts)
252 }
253 ast.ForStmt {
254 if g.cur_concrete_types.len > 0 {
255 mut stmts := node.stmts.clone()
256 return ast.Stmt(ast.ForStmt{
257 ...node
258 cond: g.expr(mut node.cond)
259 stmts: g.stmts(mut stmts)
260 })
261 }
262 node.cond = g.expr(mut node.cond)
263 node.stmts = g.stmts(mut node.stmts)
264 }
265 ast.GlobalDecl {
266 if g.cur_concrete_types.len > 0 {
267 mut fields := node.fields.clone()
268 for mut field in fields {
269 field.typ = g.unwrap_generic(field.typ)
270 field.expr = g.expr(mut field.expr)
271 }
272 return ast.Stmt(ast.GlobalDecl{
273 ...node
274 fields: fields
275 })
276 }
277 for mut field in node.fields {
278 field.expr = g.expr(mut field.expr)
279 }
280 }
281 ast.GotoLabel {}
282 ast.GotoStmt {}
283 ast.HashStmt {
284 if g.cur_concrete_types.len > 0 {
285 mut ct_conds := node.ct_conds.clone()
286 return ast.Stmt(ast.HashStmt{
287 ...node
288 ct_conds: g.exprs(mut ct_conds)
289 })
290 }
291 node.ct_conds = g.exprs(mut node.ct_conds)
292 }
293 ast.Import {}
294 ast.InterfaceDecl {}
295 ast.Module {}
296 ast.Return {
297 if g.cur_concrete_types.len > 0 {
298 mut exprs := node.exprs.clone()
299 return ast.Stmt(ast.Return{
300 ...node
301 exprs: g.exprs(mut exprs)
302 types: node.types.map(g.unwrap_generic(it))
303 })
304 }
305 node.exprs = g.exprs(mut node.exprs)
306 }
307 ast.SemicolonStmt {}
308 ast.SqlStmt {}
309 ast.StructDecl {
310 if g.cur_concrete_types.len > 0 {
311 mut fields := node.fields.clone()
312 for mut field in fields {
313 field.container_typ = g.unwrap_generic(field.container_typ)
314 field.default_expr_typ = g.unwrap_generic(field.default_expr_typ)
315 field.typ = g.unwrap_generic(field.typ)
316 field.unaliased_typ = g.unwrap_generic(field.unaliased_typ)
317 field.default_expr = g.expr(mut field.default_expr)
318 }
319 return ast.Stmt(ast.StructDecl{
320 ...node
321 fields: fields
322 })
323 }
324 for mut field in node.fields {
325 field.default_expr = g.expr(mut field.default_expr)
326 }
327 }
328 ast.TypeDecl {}
329 }
330
331 return node
332}
333
334pub fn (mut g Generics) styp(t ast.Type) string {
335 if !t.has_option_or_result() {
336 return g.base_type(t)
337 } else if t.has_flag(.option) {
338 // Register an optional if it's not registered yet
339 return g.register_option(t)
340 } else {
341 return g.register_result(t)
342 }
343}
344
345// incomplete implementation: TODO
346fn (mut g Generics) base_type(_t ast.Type) string {
347 t := g.unwrap_generic(_t)
348 if styp := g.styp_cache[t] {
349 return styp
350 }
351 if g.pref.nofloat {
352 if t == ast.f32_type {
353 return 'u32'
354 } else if t == ast.f64_type {
355 return 'u64'
356 }
357 }
358 share := t.share()
359 mut styp := if share == .atomic_t { t.atomic_typename() } else { g.cc_type(t, true) }
360 nr_muls := t.nr_muls()
361 if nr_muls > 0 {
362 styp += strings.repeat(`*`, nr_muls)
363 }
364 g.styp_cache[t] = styp
365 return styp
366}
367
368// incomplete implementation: TODO
369fn (mut g Generics) register_option(t ast.Type) string {
370 styp, _ := g.option_type_name(t)
371 return if !t.has_flag(.option_mut_param_t) { styp } else { '${styp}*' }
372}
373
374// incomplete implementation: TODO
375fn (mut g Generics) register_result(t ast.Type) string {
376 styp, _ := g.result_type_name(t)
377 return styp
378}
379
380fn (mut g Generics) option_type_name(t ast.Type) (string, string) {
381 mut base := g.base_type(t)
382 mut styp := ''
383 sym := g.table.sym(t)
384 if sym.info is ast.FnType {
385 base = 'anon_fn_${g.table.fn_type_signature(sym.info.func)}'
386 }
387 if sym.language == .c && sym.kind == .struct {
388 styp = '${option_name}_${base.replace(' ', '_')}'
389 } else {
390 styp = '${option_name}_${base}'
391 }
392 if t.has_flag(.generic) || t.is_ptr() {
393 styp = styp.replace('*', '_ptr')
394 }
395 return styp, base
396}
397
398fn (mut g Generics) result_type_name(t ast.Type) (string, string) {
399 mut base := g.base_type(t)
400 if t.has_flag(.option) {
401 g.register_option(t)
402 base = '_option_' + base
403 }
404 mut styp := ''
405 sym := g.table.sym(t)
406 if sym.info is ast.FnType {
407 base = 'anon_fn_${g.table.fn_type_signature(sym.info.func)}'
408 }
409 if sym.language == .c && sym.kind == .struct {
410 styp = '${result_name}_${base.replace(' ', '_')}'
411 } else {
412 styp = '${result_name}_${base}'
413 }
414 if t.has_flag(.generic) || t.is_ptr() {
415 styp = styp.replace('*', '_ptr')
416 }
417 return styp, base
418}
419
420// cc_type whether to prefix 'struct' or not (C__Foo -> struct Foo)
421fn (mut g Generics) cc_type(typ ast.Type, is_prefix_struct bool) string {
422 sym := g.table.sym(g.unwrap_generic(typ))
423 mut styp := sym.scoped_cname()
424 match sym.info {
425 ast.Struct, ast.Interface, ast.SumType {
426 if sym.info.is_generic && sym.generic_types.len == 0 {
427 mut sgtyps := ''
428 for gt in sym.info.generic_types {
429 gts := g.table.sym(g.unwrap_generic(gt))
430 sgtyps += '_T_${gts.scoped_cname()}'
431 }
432 styp += sgtyps
433 }
434 }
435 else {}
436 }
437
438 if is_prefix_struct && sym.language == .c {
439 styp = styp[3..]
440 if sym.kind == .struct {
441 info := sym.info as ast.Struct
442 if info.is_anon {
443 styp = 'C__' + styp
444 } else if !info.is_typedef {
445 styp = 'struct ${styp}'
446 }
447 }
448 }
449 return styp
450}
451
452pub fn (mut g Generics) method_concrete_name(old_name string, concrete_types []ast.Type, receiver_type ast.Type) string {
453 mut name := old_name
454 if receiver_type != 0 {
455 mut receiver_sym := g.table.sym(g.unwrap_generic(receiver_type))
456 if receiver_sym.info is ast.Alias {
457 unaliased_type := g.table.unaliased_type(g.unwrap_generic(receiver_type))
458 receiver_sym = g.table.sym(unaliased_type)
459 }
460 if receiver_sym.info is ast.Struct {
461 info := receiver_sym.info as ast.Struct
462 fn_conc_types := concrete_types#[info.generic_types.len..] // concrete types without the generic types of the struct
463 if fn_conc_types.len > 0 {
464 name += '_T'
465 }
466 for typ in fn_conc_types {
467 name += '_' + strings.repeat_string('__ptr__', typ.nr_muls()) +
468 g.styp(typ.set_nr_muls(0))
469 }
470 return name
471 }
472 if receiver_sym.info is ast.GenericInst {
473 info := receiver_sym.info as ast.GenericInst
474 parent_sym := g.table.sym(ast.idx_to_type(info.parent_idx))
475 if parent_sym.info is ast.Struct {
476 parent_info := parent_sym.info as ast.Struct
477 fn_conc_types := concrete_types#[parent_info.generic_types.len..]
478 if fn_conc_types.len > 0 {
479 name += '_T'
480 }
481 for typ in fn_conc_types {
482 name += '_' + strings.repeat_string('__ptr__', typ.nr_muls()) +
483 g.styp(typ.set_nr_muls(0))
484 }
485 return name
486 }
487 }
488 if receiver_sym.info is ast.Interface {
489 return name
490 }
491 }
492 if concrete_types.len > 0 {
493 name += '_T'
494 }
495 for typ in concrete_types {
496 name += '_' + strings.repeat_string('__ptr__', typ.nr_muls()) + g.styp(typ.set_nr_muls(0))
497 }
498 return name
499}
500
501pub fn (mut g Generics) concrete_name(old_name string, concrete_types []ast.Type) string {
502 mut name := old_name
503 if concrete_types.len > 0 {
504 name += '_T'
505 }
506 for typ in concrete_types {
507 name += '_' + strings.repeat_string('__ptr__', typ.nr_muls()) + g.styp(typ.set_nr_muls(0))
508 }
509 return name
510}
511
512pub fn (mut g Generics) generic_fn_decl(mut node ast.FnDecl) []ast.Stmt {
513 mut solved_fns := []ast.Stmt{}
514 nkey := node.fkey()
515 generic_types_by_fn := g.table.fn_generic_types[nkey]
516 for concrete_types in generic_types_by_fn {
517 if g.pref.is_verbose {
518 syms := concrete_types.map(g.table.sym(it))
519 the_type := syms.map(it.name).join(', ')
520 println('solve generic fn `${node.name}` for type `${the_type}`')
521 }
522 g.cur_concrete_types = concrete_types
523
524 mut new_node := ast.FnDecl{
525 ...node
526 }
527 new_node = g.stmt(mut new_node) as ast.FnDecl
528 new_node = ast.FnDecl{
529 ...new_node
530 name: if node.is_method {
531 g.method_concrete_name(new_node.name, concrete_types, new_node.receiver.typ)
532 } else {
533 g.concrete_name(new_node.name, concrete_types)
534 }
535 ninstances: 0
536 generic_names: []
537 }
538 if new_node.is_method {
539 mut sym := g.table.sym(new_node.receiver.typ)
540 func := ast.Fn{
541 is_variadic: new_node.is_variadic
542 is_c_variadic: new_node.is_c_variadic
543 language: .v
544 is_pub: new_node.is_pub
545 is_deprecated: new_node.is_deprecated
546 is_noreturn: new_node.is_noreturn
547 is_unsafe: new_node.is_unsafe
548 is_must_use: new_node.is_must_use
549 is_keep_alive: new_node.is_keep_alive
550 is_method: new_node.is_method
551 is_static_type_method: new_node.is_static_type_method
552 no_body: new_node.no_body
553 is_file_translated: new_node.is_file_translated
554 mod: new_node.mod
555 file: new_node.file
556 file_mode: new_node.file_mode
557 pos: new_node.pos
558 return_type_pos: new_node.return_type_pos
559 return_type: new_node.return_type
560 receiver_type: new_node.receiver.typ
561 name: new_node.name
562 params: new_node.params
563 generic_names: []
564 is_conditional: new_node.is_conditional
565 ctdefine_idx: new_node.ctdefine_idx
566 is_expand_simple_interpolation: new_node.is_expand_simple_interpolation
567 }
568 g.table.find_or_register_fn_type(func, false, true)
569 sym.register_method(func)
570 }
571 solved_fns << new_node
572 }
573 g.cur_concrete_types = []
574 return solved_fns
575}
576
577pub fn (mut g Generics) exprs(mut nodes []ast.Expr) []ast.Expr {
578 for mut e in nodes {
579 e = g.expr(mut e)
580 }
581 return nodes
582}
583
584pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
585 match mut node {
586 ast.AnonFn {
587 if g.cur_concrete_types.len > 0 {
588 return ast.Expr(ast.AnonFn{
589 ...node
590 typ: g.unwrap_generic(node.typ)
591 decl: g.stmt(mut node.decl) as ast.FnDecl
592 })
593 }
594 node.decl = g.stmt(mut node.decl) as ast.FnDecl
595 }
596 ast.ArrayDecompose {
597 if g.cur_concrete_types.len > 0 {
598 return ast.Expr(ast.ArrayDecompose{
599 ...node
600 expr_type: g.unwrap_generic(node.expr_type)
601 arg_type: g.unwrap_generic(node.arg_type)
602 expr: g.expr(mut node.expr)
603 })
604 }
605 node.expr = g.expr(mut node.expr)
606 }
607 ast.ArrayInit {
608 if g.cur_concrete_types.len > 0 {
609 mut exprs := node.exprs.clone()
610 return ast.Expr(ast.ArrayInit{
611 ...node
612 exprs: g.exprs(mut exprs)
613 expr_types: node.expr_types.map(g.unwrap_generic(it))
614 typ: g.unwrap_generic(node.typ)
615 elem_type: g.unwrap_generic(node.elem_type)
616 alias_type: g.unwrap_generic(node.alias_type)
617 len_expr: g.expr(mut node.len_expr)
618 cap_expr: g.expr(mut node.cap_expr)
619 init_type: g.unwrap_generic(node.init_type)
620 init_expr: g.expr(mut node.init_expr)
621 })
622 }
623 node.exprs = g.exprs(mut node.exprs)
624 if node.has_len {
625 node.len_expr = g.expr(mut node.len_expr)
626 }
627 if node.has_cap {
628 node.cap_expr = g.expr(mut node.cap_expr)
629 }
630 if node.has_init {
631 node.init_expr = g.expr(mut node.init_expr)
632 }
633 }
634 ast.AsCast {
635 if g.cur_concrete_types.len > 0 {
636 return ast.Expr(ast.AsCast{
637 ...node
638 typ: g.unwrap_generic(node.typ)
639 expr_type: g.unwrap_generic(node.expr_type)
640 expr: g.expr(mut node.expr)
641 })
642 } else {
643 node.expr = g.expr(mut node.expr)
644 }
645 }
646 ast.CallExpr {
647 if g.cur_concrete_types.len > 0 {
648 mut args := node.args.clone()
649 mut all_concrete_types := node.concrete_types.clone()
650 mut has_ct_args := false
651 for mut ct in all_concrete_types {
652 idx := g.cur_fn.generic_names.index(g.table.type_str(ct))
653 if idx != -1 {
654 ct = g.cur_concrete_types[idx]
655 }
656 }
657 for i, mut arg in args {
658 if arg.typ.has_flag(.generic) {
659 arg.typ = g.unwrap_generic(arg.typ)
660 arg.ct_expr = false
661 }
662 arg.expr = g.expr(mut arg.expr)
663 has_ct_args = has_ct_args || arg.ct_expr
664 if mut arg.expr is ast.Ident {
665 // Solve concrete_types when the type of one argument was elem in `for elem in my_array` when my_array is T
666 forin_type := g.forin_types[arg.expr.name]
667 if forin_type != 0 {
668 if func := g.table.find_fn(node.name) {
669 solved_type_generic_name := g.table.type_str(func.params[i].typ)
670 idx := func.generic_names.index(solved_type_generic_name)
671 if idx != -1 {
672 all_concrete_types[idx] = forin_type
673 }
674 }
675 }
676 }
677 }
678 mut receiver_type := g.unwrap_generic(node.receiver_type)
679 if receiver_type.has_flag(.generic) {
680 receiver_type = receiver_type.clear_flag(.generic)
681 }
682 call_name := if node.is_fn_var {
683 node.name
684 } else if has_ct_args {
685 node.name
686 } else if node.is_method {
687 g.method_concrete_name(node.name, all_concrete_types, node.receiver_type)
688 } else {
689 g.concrete_name(node.name, all_concrete_types)
690 }
691 return ast.Expr(ast.CallExpr{
692 ...node
693 name: call_name
694 left_type: g.unwrap_generic(node.left_type)
695 receiver_type: receiver_type
696 return_type: g.unwrap_generic(node.return_type)
697 return_type_generic: ast.no_type
698 fn_var_type: g.unwrap_generic(node.fn_var_type)
699 left: g.expr(mut node.left)
700 expected_arg_types: node.expected_arg_types.map(g.unwrap_generic(it))
701 args: args
702 concrete_types: []
703 raw_concrete_types: node.raw_concrete_types.clone()
704 from_embed_types: node.from_embed_types.clone()
705 or_block: g.expr(mut node.or_block) as ast.OrExpr
706 })
707 }
708 node.left = g.expr(mut node.left)
709 mut has_ct_args := false
710 for mut arg in node.args {
711 arg.expr = g.expr(mut arg.expr)
712 has_ct_args = has_ct_args || arg.ct_expr
713 }
714 node.or_block = g.expr(mut node.or_block) as ast.OrExpr
715 if node.is_method && g.table.sym(node.receiver_type).info is ast.Alias {
716 // Workaround needed for markused
717 alias_sym := g.table.sym(g.unwrap_generic(node.receiver_type))
718 unaliased_type := g.table.unaliased_type(g.unwrap_generic(node.receiver_type))
719 if !alias_sym.has_method(node.name)
720 && g.table.sym(unaliased_type).has_method(node.name) {
721 node.receiver_type = unaliased_type
722 }
723 }
724 if node.receiver_type.has_flag(.generic) {
725 node.receiver_type = node.receiver_type.clear_flag(.generic)
726 }
727 if node.concrete_types.len > 0 {
728 if func := g.table.find_fn(node.name) {
729 node.expected_arg_types = node.expected_arg_types.map(g.table.convert_generic_type(it,
730 func.generic_names, node.concrete_types) or { it })
731 }
732 }
733 if !node.is_fn_var {
734 node.name = if node.is_method {
735 if has_ct_args {
736 node.name
737 } else {
738 g.method_concrete_name(node.name, node.concrete_types, node.receiver_type)
739 }
740 } else {
741 if has_ct_args {
742 node.name
743 } else {
744 g.concrete_name(node.name, node.concrete_types)
745 }
746 }
747 }
748 return ast.Expr(ast.CallExpr{
749 ...node
750 concrete_types: []
751 raw_concrete_types: if node.raw_concrete_types.len > 0 {
752 node.raw_concrete_types.clone()
753 } else {
754 node.concrete_types.clone()
755 }
756 })
757 }
758 ast.CastExpr {
759 if g.cur_concrete_types.len > 0 {
760 return ast.Expr(ast.CastExpr{
761 ...node
762 typ: g.unwrap_generic(node.typ)
763 arg: g.expr(mut node.arg)
764 expr: g.expr(mut node.expr)
765 })
766 }
767 node.arg = g.expr(mut node.arg)
768 node.expr = g.expr(mut node.expr)
769 }
770 ast.ChanInit {
771 if g.cur_concrete_types.len > 0 {
772 return ast.Expr(ast.ChanInit{
773 ...node
774 typ: g.unwrap_generic(node.typ)
775 elem_type: g.unwrap_generic(node.typ)
776 cap_expr: g.expr(mut node.cap_expr)
777 })
778 }
779 node.cap_expr = g.expr(mut node.cap_expr)
780 }
781 ast.ComptimeCall {
782 if g.cur_concrete_types.len > 0 {
783 mut args := node.args.clone()
784 for mut arg in args {
785 arg.expr = g.expr(mut arg.expr)
786 }
787 return ast.Expr(ast.ComptimeCall{
788 ...node
789 left_type: g.unwrap_generic(node.left_type)
790 result_type: g.unwrap_generic(node.result_type)
791 args: args
792 })
793 }
794 for mut arg in node.args {
795 arg.expr = g.expr(mut arg.expr)
796 }
797 }
798 ast.ComptimeSelector {
799 if g.cur_concrete_types.len > 0 {
800 return ast.Expr(ast.ComptimeSelector{
801 ...node
802 left_type: g.unwrap_generic(node.left_type)
803 typ: g.unwrap_generic(node.typ)
804 left: g.expr(mut node.left)
805 field_expr: g.expr(mut node.field_expr)
806 })
807 }
808 node.left = g.expr(mut node.left)
809 node.field_expr = g.expr(mut node.field_expr)
810 }
811 ast.ConcatExpr {
812 if g.cur_concrete_types.len > 0 {
813 mut vals := node.vals.clone()
814 for mut val in vals {
815 val = g.expr(mut val)
816 }
817 return ast.Expr(ast.ConcatExpr{
818 ...node
819 return_type: g.unwrap_generic(node.return_type)
820 vals: vals
821 })
822 }
823 for mut val in node.vals {
824 val = g.expr(mut val)
825 }
826 }
827 ast.DumpExpr {
828 if g.cur_concrete_types.len > 0 {
829 name := if mut node.expr is ast.Ident {
830 // var
831 if node.expr.info is ast.IdentVar && node.expr.language == .v {
832 ident_info := node.expr.var_info()
833 g.styp(g.unwrap_generic(ident_info.typ.clear_flags(.shared_f, .result))).replace('*',
834 '')
835 } else {
836 node.cname
837 }
838 } else if mut node.expr is ast.CallExpr {
839 g.styp(g.unwrap_generic(node.expr_type.clear_flags(.shared_f, .result))).replace('*',
840 '').replace('.', '__')
841 } else {
842 node.cname
843 }
844 return ast.Expr(ast.DumpExpr{
845 ...node
846 cname: name
847 expr_type: g.unwrap_generic(node.expr_type)
848 expr: g.expr(mut node.expr)
849 })
850 }
851 node.expr = g.expr(mut node.expr)
852 }
853 ast.Ident {
854 match mut node.obj {
855 ast.Var {
856 if g.cur_concrete_types.len > 0 {
857 is_ct_type_generic := node.obj.ct_type_var == .generic_param
858 || node.obj.ct_type_var == .generic_var
859 is_ct_type_forin_val := node.obj.ct_type_var == .value_var // elem in `for elem in my_array` when my_array is T
860 unwrapped_typ := if is_ct_type_forin_val {
861 g.forin_types[node.name]
862 } else {
863 g.unwrap_generic(node.obj.typ)
864 }
865 info := match node.info {
866 ast.IdentVar {
867 ast.IdentInfo(ast.IdentVar{
868 ...node.info as ast.IdentVar
869 typ: g.unwrap_generic(node.info.typ)
870 })
871 }
872 ast.IdentFn {
873 ast.IdentInfo(ast.IdentFn{
874 ...node.info as ast.IdentFn
875 typ: g.unwrap_generic(node.info.typ)
876 })
877 }
878 }
879
880 return ast.Expr(ast.Ident{
881 ...node
882 obj: ast.Var{
883 ...node.obj
884 typ: unwrapped_typ
885 smartcasts: node.obj.smartcasts.map(g.unwrap_generic(it))
886 is_auto_deref: node.obj.is_auto_deref
887 || (node.obj.typ.has_flag(.generic)
888 && g.table.sym(unwrapped_typ).kind in [.sum_type, .interface])
889 // node.obj.orig_type = g.unwrap_generic(node.obj.orig_type)
890 ct_type_unwrapped: is_ct_type_generic || is_ct_type_forin_val
891 || node.obj.ct_type_unwrapped
892 ct_type_var: if is_ct_type_generic || is_ct_type_forin_val {
893 .no_comptime
894 } else {
895 node.obj.ct_type_var
896 }
897 }
898 info: info
899 ct_expr: !is_ct_type_forin_val && node.ct_expr
900 })
901 }
902 }
903 ast.EmptyScopeObject {
904 if g.cur_concrete_types.len > 0 {
905 mut typ := node.obj.typ
906 mut name := node.name
907 if typ == 0 {
908 if g.cur_fn != unsafe { nil } {
909 idx := g.cur_fn.generic_names.index(node.name)
910 if idx != -1 {
911 typ = g.cur_concrete_types[idx]
912 name = g.table.type_str(typ)
913 }
914 }
915 } else {
916 typ = g.unwrap_generic(typ)
917 name = g.table.type_str(typ)
918 }
919 return ast.Expr(ast.Ident{
920 ...node
921 obj: ast.EmptyScopeObject{
922 ...node.obj
923 typ: typ
924 name: name
925 }
926 name: name
927 })
928 }
929 }
930 else {}
931 }
932 }
933 ast.IfExpr {
934 if g.cur_concrete_types.len > 0 {
935 mut branches := node.branches.clone()
936 for mut branch in branches {
937 branch.stmts = branch.stmts.clone()
938 branch.cond = g.expr(mut branch.cond)
939 branch.stmts = g.stmts(mut branch.stmts)
940 }
941 return ast.Expr(ast.IfExpr{
942 ...node
943 typ: g.unwrap_generic(node.typ)
944 branches: branches
945 left: g.expr(mut node.left)
946 })
947 }
948 for mut branch in node.branches {
949 branch.cond = g.expr(mut branch.cond)
950 branch.stmts = g.stmts(mut branch.stmts)
951 }
952 node.left = g.expr(mut node.left)
953 }
954 ast.IfGuardExpr {
955 if g.cur_concrete_types.len > 0 {
956 return ast.Expr(ast.IfGuardExpr{
957 ...node
958 expr_type: g.unwrap_generic(node.expr_type)
959 expr: g.expr(mut node.expr)
960 })
961 }
962 node.expr = g.expr(mut node.expr)
963 }
964 ast.IndexExpr {
965 mut indices := []ast.Expr{cap: node.indices.len}
966 for mut index in node.indices {
967 indices << g.expr(mut index)
968 }
969 if g.cur_concrete_types.len > 0 {
970 return ast.Expr(ast.IndexExpr{
971 ...node
972 left_type: g.unwrap_generic(node.left_type)
973 typ: g.unwrap_generic(node.typ)
974 left: g.expr(mut node.left)
975 index: g.expr(mut node.index)
976 indices: indices
977 or_expr: g.expr(mut node.or_expr) as ast.OrExpr
978 })
979 }
980 node.left = g.expr(mut node.left)
981 node.index = g.expr(mut node.index)
982 node.indices = indices
983 node.or_expr = g.expr(mut node.or_expr) as ast.OrExpr
984 }
985 ast.InfixExpr {
986 if g.cur_concrete_types.len > 0 {
987 return ast.Expr(ast.InfixExpr{
988 ...node
989 left_type: g.unwrap_generic(node.left_type)
990 right_type: g.unwrap_generic(node.right_type)
991 promoted_type: g.unwrap_generic(node.promoted_type)
992 left: g.expr(mut node.left)
993 right: g.expr(mut node.right)
994 })
995 }
996 node.left = g.expr(mut node.left)
997 node.right = g.expr(mut node.right)
998 }
999 ast.IsRefType {
1000 if g.cur_concrete_types.len > 0 {
1001 return ast.Expr(ast.IsRefType{
1002 ...node
1003 typ: g.unwrap_generic(node.typ)
1004 expr: g.expr(mut node.expr)
1005 })
1006 }
1007 node.expr = g.expr(mut node.expr)
1008 }
1009 ast.Likely {
1010 if g.cur_concrete_types.len > 0 {
1011 return ast.Expr(ast.Likely{
1012 ...node
1013 expr: g.expr(mut node.expr)
1014 })
1015 }
1016 node.expr = g.expr(mut node.expr)
1017 }
1018 ast.LockExpr {
1019 if g.cur_concrete_types.len > 0 {
1020 mut stmts := node.stmts.clone()
1021 mut lockeds := node.lockeds.clone()
1022 return ast.Expr(ast.LockExpr{
1023 ...node
1024 typ: g.unwrap_generic(node.typ)
1025 stmts: g.stmts(mut stmts)
1026 lockeds: g.exprs(mut lockeds)
1027 })
1028 }
1029 node.stmts = g.stmts(mut node.stmts)
1030 node.lockeds = g.exprs(mut node.lockeds)
1031 }
1032 ast.MapInit {
1033 if g.cur_concrete_types.len > 0 {
1034 mut keys := node.keys.clone()
1035 mut vals := node.vals.clone()
1036 return ast.Expr(ast.MapInit{
1037 typ: g.unwrap_generic(node.typ)
1038 key_type: g.unwrap_generic(node.key_type)
1039 value_type: g.unwrap_generic(node.value_type)
1040 val_types: node.val_types.map(g.unwrap_generic(it))
1041 keys: g.exprs(mut keys)
1042 vals: g.exprs(mut vals)
1043 })
1044 }
1045 node.keys = g.exprs(mut node.keys)
1046 node.vals = g.exprs(mut node.vals)
1047 }
1048 ast.MatchExpr {
1049 if g.cur_concrete_types.len > 0 {
1050 mut branches := node.branches.clone()
1051 for mut branch in branches {
1052 branch.stmts = branch.stmts.clone()
1053 branch.exprs = branch.exprs.clone()
1054 branch.exprs = g.exprs(mut branch.exprs)
1055 branch.stmts = g.stmts(mut branch.stmts)
1056 }
1057 return ast.Expr(ast.MatchExpr{
1058 ...node
1059 branches: branches
1060 return_type: g.unwrap_generic(node.return_type)
1061 cond_type: g.unwrap_generic(node.cond_type)
1062 cond: g.expr(mut node.cond)
1063 expected_type: g.unwrap_generic(node.expected_type)
1064 })
1065 }
1066 node.cond = g.expr(mut node.cond)
1067 for mut branch in node.branches {
1068 branch.exprs = g.exprs(mut branch.exprs)
1069 branch.stmts = g.stmts(mut branch.stmts)
1070 }
1071 }
1072 ast.OrExpr {
1073 if g.cur_concrete_types.len > 0 {
1074 mut stmts := node.stmts.clone()
1075 return ast.Expr(ast.OrExpr{
1076 ...node
1077 stmts: g.stmts(mut stmts)
1078 })
1079 }
1080 node.stmts = g.stmts(mut node.stmts)
1081 }
1082 ast.ParExpr {
1083 if g.cur_concrete_types.len > 0 {
1084 return ast.Expr(ast.ParExpr{
1085 ...node
1086 expr: g.expr(mut node.expr)
1087 })
1088 }
1089 node.expr = g.expr(mut node.expr)
1090 }
1091 ast.PostfixExpr {
1092 if g.cur_concrete_types.len > 0 {
1093 return ast.Expr(ast.PostfixExpr{
1094 ...node
1095 expr: g.expr(mut node.expr)
1096 typ: g.unwrap_generic(node.typ)
1097 })
1098 }
1099 node.expr = g.expr(mut node.expr)
1100 }
1101 ast.PrefixExpr {
1102 if g.cur_concrete_types.len > 0 {
1103 return ast.Expr(ast.PrefixExpr{
1104 ...node
1105 right_type: g.unwrap_generic(node.right_type)
1106 right: g.expr(mut node.right)
1107 or_block: g.expr(mut node.or_block) as ast.OrExpr
1108 })
1109 }
1110 node.right = g.expr(mut node.right)
1111 node.or_block = g.expr(mut node.or_block) as ast.OrExpr
1112 }
1113 ast.RangeExpr {
1114 if g.cur_concrete_types.len > 0 {
1115 return ast.Expr(ast.RangeExpr{
1116 ...node
1117 typ: g.unwrap_generic(node.typ)
1118 low: g.expr(mut node.low)
1119 high: g.expr(mut node.high)
1120 })
1121 }
1122 node.low = g.expr(mut node.low)
1123 node.high = g.expr(mut node.high)
1124 }
1125 ast.SelectExpr {
1126 if g.cur_concrete_types.len > 0 {
1127 mut branches := node.branches.clone()
1128 for mut branch in node.branches {
1129 branch.stmt = g.stmt(mut branch.stmt)
1130 branch.stmts = branch.stmts.clone()
1131 branch.stmts = g.stmts(mut branch.stmts)
1132 }
1133 return ast.Expr(ast.SelectExpr{
1134 ...node
1135 expected_type: g.unwrap_generic(node.expected_type)
1136 branches: branches
1137 })
1138 }
1139 for mut branch in node.branches {
1140 branch.stmt = g.stmt(mut branch.stmt)
1141 branch.stmts = g.stmts(mut branch.stmts)
1142 }
1143 }
1144 ast.SelectorExpr {
1145 if g.cur_concrete_types.len > 0 {
1146 return ast.Expr(ast.SelectorExpr{
1147 ...node
1148 expr: g.expr(mut node.expr)
1149 expr_type: g.unwrap_generic(node.expr_type)
1150 typ: g.unwrap_generic(node.typ)
1151 name_type: g.unwrap_generic(node.name_type)
1152 from_embed_types: node.from_embed_types.map(g.unwrap_generic(it))
1153 })
1154 }
1155 node.expr = g.expr(mut node.expr)
1156 }
1157 ast.SizeOf {
1158 if g.cur_concrete_types.len > 0 {
1159 return ast.Expr(ast.SizeOf{
1160 ...node
1161 expr: g.expr(mut node.expr)
1162 typ: g.unwrap_generic(node.typ)
1163 })
1164 }
1165 node.expr = g.expr(mut node.expr)
1166 }
1167 ast.SqlExpr {
1168 if g.cur_concrete_types.len > 0 {
1169 mut fields := node.fields.clone()
1170 for mut field in fields {
1171 field.default_expr = g.expr(mut field.default_expr)
1172 }
1173 mut sub_structs := node.sub_structs.clone()
1174 for _, mut sub_struct in sub_structs {
1175 sub_struct = g.expr(mut sub_struct) as ast.SqlExpr
1176 }
1177 return ast.Expr(ast.SqlExpr{
1178 ...node
1179 typ: g.unwrap_generic(node.typ)
1180 db_expr: g.expr(mut node.db_expr)
1181 where_expr: g.expr(mut node.where_expr)
1182 order_expr: g.expr(mut node.order_expr)
1183 limit_expr: g.expr(mut node.limit_expr)
1184 offset_expr: g.expr(mut node.offset_expr)
1185 fields: fields
1186 sub_structs: sub_structs
1187 })
1188 }
1189 node.db_expr = g.expr(mut node.db_expr)
1190 if node.has_where {
1191 node.where_expr = g.expr(mut node.where_expr)
1192 }
1193 if node.has_order {
1194 node.order_expr = g.expr(mut node.order_expr)
1195 }
1196 if node.has_limit {
1197 node.limit_expr = g.expr(mut node.limit_expr)
1198 }
1199 if node.has_offset {
1200 node.offset_expr = g.expr(mut node.offset_expr)
1201 }
1202 for mut field in node.fields {
1203 field.default_expr = g.expr(mut field.default_expr)
1204 }
1205 for _, mut sub_struct in node.sub_structs {
1206 sub_struct = g.expr(mut sub_struct) as ast.SqlExpr
1207 }
1208 }
1209 ast.SqlQueryDataExpr {
1210 items := g.sql_query_data_items(node.items)
1211 if g.cur_concrete_types.len > 0 {
1212 return ast.Expr(ast.SqlQueryDataExpr{
1213 ...node
1214 items: items
1215 typ: g.unwrap_generic(node.typ)
1216 })
1217 }
1218 node.items = items
1219 }
1220 ast.StringInterLiteral {
1221 if g.cur_concrete_types.len > 0 {
1222 mut exprs := node.exprs.clone()
1223 mut fwidth_exprs := node.fwidth_exprs.clone()
1224 mut precision_exprs := node.precision_exprs.clone()
1225 return ast.Expr(ast.StringInterLiteral{
1226 ...node
1227 exprs: g.exprs(mut exprs)
1228 expr_types: node.expr_types.map(g.unwrap_generic(it))
1229 fwidth_exprs: g.exprs(mut fwidth_exprs)
1230 precision_exprs: g.exprs(mut precision_exprs)
1231 })
1232 }
1233 node.exprs = g.exprs(mut node.exprs)
1234 node.fwidth_exprs = g.exprs(mut node.fwidth_exprs)
1235 node.precision_exprs = g.exprs(mut node.precision_exprs)
1236 }
1237 ast.StructInit {
1238 if g.cur_concrete_types.len > 0 {
1239 old_inside_struct_init := g.inside_struct_init
1240 g.inside_struct_init = true
1241 old_cur_struct_init_node := g.cur_struct_init_node
1242 g.cur_struct_init_node = unsafe { &node }
1243
1244 mut init_fields := node.init_fields.clone()
1245 for mut init_field in init_fields {
1246 init_field.expr = g.expr(mut init_field.expr)
1247 init_field.typ = g.unwrap_generic(init_field.typ)
1248 init_field.expected_type = g.unwrap_generic(init_field.expected_type)
1249 init_field.parent_type = g.unwrap_generic(init_field.parent_type)
1250 }
1251
1252 out := ast.Expr(ast.StructInit{
1253 ...node
1254 typ: g.unwrap_generic(node.typ)
1255 typ_str: g.table.type_str(g.unwrap_generic(node.typ))
1256 generic_types: node.generic_types.map(g.unwrap_generic(it))
1257 update_expr: g.expr(mut node.update_expr)
1258 update_expr_type: g.unwrap_generic(node.update_expr_type)
1259 init_fields: init_fields
1260 })
1261
1262 g.cur_struct_init_node = old_cur_struct_init_node
1263 g.inside_struct_init = old_inside_struct_init
1264 return out
1265 }
1266 old_inside_struct_init := g.inside_struct_init
1267 g.inside_struct_init = true
1268 node.update_expr = g.expr(mut node.update_expr)
1269 for mut init_field in node.init_fields {
1270 init_field.expr = g.expr(mut init_field.expr)
1271 }
1272 g.inside_struct_init = old_inside_struct_init
1273 }
1274 ast.TypeNode {
1275 if g.cur_concrete_types.len > 0 {
1276 return ast.Expr(ast.TypeNode{
1277 ...node
1278 typ: g.unwrap_generic(node.typ)
1279 stmt: g.stmt(mut node.stmt)
1280 })
1281 }
1282 node.stmt = g.stmt(mut node.stmt)
1283 }
1284 ast.TypeOf {
1285 if g.cur_concrete_types.len > 0 {
1286 return ast.Expr(ast.TypeOf{
1287 ...node
1288 typ: g.unwrap_generic(node.typ)
1289 expr: g.expr(mut node.expr)
1290 })
1291 }
1292 node.expr = g.expr(mut node.expr)
1293 }
1294 ast.UnsafeExpr {
1295 if g.cur_concrete_types.len > 0 {
1296 return ast.Expr(ast.UnsafeExpr{
1297 ...node
1298 expr: g.expr(mut node.expr)
1299 })
1300 }
1301 node.expr = g.expr(mut node.expr)
1302 }
1303 else {}
1304 }
1305
1306 return node
1307}
1308
1309fn (mut g Generics) sql_query_data_items(items []ast.SqlQueryDataItem) []ast.SqlQueryDataItem {
1310 mut new_items := []ast.SqlQueryDataItem{cap: items.len}
1311 for item in items {
1312 mut item_copy := item
1313 new_items << g.sql_query_data_item(mut item_copy)
1314 }
1315 return new_items
1316}
1317
1318fn (mut g Generics) sql_query_data_item(mut item ast.SqlQueryDataItem) ast.SqlQueryDataItem {
1319 match mut item {
1320 ast.SqlQueryDataLeaf {
1321 item.expr = g.expr(mut item.expr)
1322 }
1323 ast.SqlQueryDataIf {
1324 for mut branch in item.branches {
1325 branch.cond = g.expr(mut branch.cond)
1326 branch.items = g.sql_query_data_items(branch.items)
1327 }
1328 }
1329 }
1330
1331 return item
1332}
1333
1334fn (mut g Generics) unwrap_generic(typ ast.Type) ast.Type {
1335 if typ.has_flag(.generic) {
1336 if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 {
1337 if t_typ := g.table.convert_generic_type(typ, g.cur_fn.generic_names,
1338 g.cur_concrete_types)
1339 {
1340 return t_typ
1341 }
1342 }
1343 if g.inside_struct_init && g.cur_struct_init_node != unsafe { nil } {
1344 if g.cur_struct_init_node.typ != 0 {
1345 sym := g.table.sym(g.cur_struct_init_node.typ)
1346 if sym.info is ast.Struct {
1347 if sym.info.generic_types.len > 0 {
1348 generic_names := sym.info.generic_types.map(g.table.sym(it).name)
1349 if t_typ := g.table.convert_generic_type(typ, generic_names,
1350 g.cur_struct_init_node.generic_types.map(g.unwrap_generic(it)))
1351 {
1352 return t_typ
1353 }
1354 }
1355 }
1356 }
1357 } else if g.table.sym(typ).kind == .struct {
1358 // resolve selector `a.foo` where `a` is struct[T] on non generic function
1359 sym := g.table.sym(typ)
1360 if sym.info is ast.Struct {
1361 if sym.info.generic_types.len > 0 {
1362 generic_names := sym.info.generic_types.map(g.table.sym(it).name)
1363 if t_typ := g.table.convert_generic_type(typ, generic_names,
1364 sym.info.concrete_types)
1365 {
1366 return t_typ
1367 }
1368
1369 if t_typ := g.table.convert_generic_type(typ, generic_names,
1370 g.cur_concrete_types)
1371 {
1372 return t_typ
1373 }
1374 }
1375 }
1376 }
1377 }
1378 return typ
1379}
1380