vxx / vlib / v / transformer / array.v
104 lines · 101 sloc · 2.71 KB · 16e9dff060e9e7db1a6fdd8d171127734d6a6849
Raw
1// Copyright (c) 2019-2025 Alexander Medvednikov. 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 transformer
5
6import v.ast
7
8pub fn (mut t Transformer) array_init(mut node ast.ArrayInit) ast.Expr {
9 for mut expr in node.exprs {
10 expr = t.expr(mut expr)
11 }
12 if node.has_len {
13 node.len_expr = t.expr(mut node.len_expr)
14 }
15 if node.has_cap {
16 node.cap_expr = t.expr(mut node.cap_expr)
17 }
18 if node.has_init {
19 node.init_expr = t.expr(mut node.init_expr)
20 }
21 if node.has_update_expr {
22 node.update_expr = t.expr(mut node.update_expr)
23 }
24 if t.pref.backend == .js_node || !t.pref.new_transform || t.skip_array_transform
25 || node.is_fixed || t.inside_in || node.has_len || node.has_cap || node.exprs.len == 0
26 || node.has_update_expr {
27 return node
28 }
29 // For C and native transform into a function call `builtin__new_array_from_c_array_noscan(...)` etc
30 len := node.exprs.len
31 len_arg := ast.CallArg{
32 expr: ast.IntegerLiteral{
33 val: len.str()
34 }
35 typ: ast.int_type
36 }
37 sizeof_arg := ast.CallArg{
38 expr: ast.SizeOf{
39 is_type: true
40 typ: node.elem_type
41 }
42 typ: ast.int_type
43 }
44 fixed_array_idx := t.table.find_or_register_array_fixed(node.elem_type, len, ast.empty_expr,
45 false)
46 fixed_array_typ := if node.elem_type.has_flag(.generic) {
47 ast.new_type(fixed_array_idx).set_flag(.generic)
48 } else {
49 ast.new_type(fixed_array_idx)
50 }
51 fixed_array_arg := ast.CallArg{
52 expr: ast.CastExpr{
53 expr: ast.ArrayInit{
54 is_fixed: true
55 has_val: true
56 typ: fixed_array_typ
57 elem_type: node.elem_type
58 exprs: node.exprs
59 expr_types: node.expr_types
60 }
61 typ: ast.voidptr_type
62 typname: 'voidptr'
63 expr_type: fixed_array_typ
64 }
65 typ: ast.voidptr_type_idx
66 }
67 mut call_expr := ast.CallExpr{
68 name: 'new_array_from_c_array'
69 mod: 'builtin'
70 scope: unsafe { nil }
71 args: [len_arg, len_arg, sizeof_arg, fixed_array_arg] //, sizeof(voidptr), _MOV((voidptr[${len}]){')
72 return_type: node.typ
73 }
74 return call_expr
75}
76
77pub fn (mut t Transformer) find_new_array_len(node ast.AssignStmt) {
78 if !t.pref.is_prod {
79 return
80 }
81 // looking for, array := []type{len:int}
82 mut right := node.right[0]
83 if mut right is ast.ArrayInit {
84 mut left := node.left[0]
85 if mut left is ast.Ident {
86 // we can not analyse mut array
87 if left.is_mut {
88 t.index.safe_access(left.name, -2)
89 return
90 }
91 // as we do not need to check any value under the setup len
92 if !right.has_len {
93 t.index.safe_access(left.name, -1)
94 return
95 }
96 mut len := int(0)
97 value := right.len_expr
98 if value is ast.IntegerLiteral {
99 len = value.val.int() + 1
100 }
101 t.index.safe_access(left.name, len)
102 }
103 }
104}
105