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