@@ -31,6 +31,18 @@ fn array_fixed_type(t types.Type) ?types.ArrayFixed {
3131 return none
3232}
3333
34+ fn fixed_array_index_info (t types.Type) (bool , bool , types.ArrayFixed) {
35+ if fixed := array_fixed_type (t) {
36+ return true , false , fixed
37+ }
38+ if t is types.Pointer {
39+ if fixed := array_fixed_type (t.base_type) {
40+ return true , true , fixed
41+ }
42+ }
43+ return false , false , types.ArrayFixed{}
44+ }
45+
3446// gen_array_literal_value emits array literal value output for c.
3547fn (mut g FlatGen) gen_array_literal_value (node flat.Node, elem_type types.Type) {
3648 c_elem := g.tc.c_type (elem_type)
@@ -49,6 +61,32 @@ fn (mut g FlatGen) gen_array_literal_value(node flat.Node, elem_type types.Type)
4961 g.write ('})' )
5062}
5163
64+ fn (mut g FlatGen) gen_array_literal_ptr_arg (node flat.Node, elem_type types.Type) {
65+ c_elem := g.tc.c_type (elem_type)
66+ g.write ('(${c_elem }[]){' )
67+ for i in 0 .. node.children_count {
68+ if i > 0 {
69+ g.write (', ' )
70+ }
71+ g.gen_expr_with_expected_type (g.a.child (& node, i), elem_type)
72+ }
73+ if node.children_count == 0 {
74+ g.write ('0' )
75+ }
76+ g.write ('}' )
77+ }
78+
79+ fn (mut g FlatGen) gen_pointer_arg_from_array_literal (node flat.Node, expected types.Type) bool {
80+ if node.kind != .array_literal {
81+ return false
82+ }
83+ if expected is types.Pointer {
84+ g.gen_array_literal_ptr_arg (node, expected.base_type)
85+ return true
86+ }
87+ return false
88+ }
89+
5290// gen_fixed_array_data_arg emits fixed array data arg output for c.
5391fn (mut g FlatGen) gen_fixed_array_data_arg (id flat.NodeId, arr types.ArrayFixed) {
5492 node := g.a.nodes[int (id)]
@@ -64,6 +102,14 @@ fn (mut g FlatGen) gen_fixed_array_data_arg(id flat.NodeId, arr types.ArrayFixed
64102 g.write ('}' )
65103 return
66104 }
105+ if node.kind == .postfix && node.children_count > 0 {
106+ child_id := g.a.child (& node, 0 )
107+ child := g.a.nodes[int (child_id)]
108+ if child.kind == .array_literal {
109+ g.gen_fixed_array_data_arg (child_id, arr)
110+ return
111+ }
112+ }
67113 g.gen_expr (id)
68114}
69115
@@ -81,11 +127,13 @@ fn (mut g FlatGen) gen_array_push_many_stmt(lhs_id flat.NodeId, rhs_id flat.Node
81127 g.writeln (', ${len_expr });' )
82128 return
83129 }
84- g.write ('array_push_many(${amp }' )
85- gen_expr_lvalue (mut g, lhs_id)
86- g.write (', ' )
130+ tmp := g.tmp_name ()
131+ g.write ('{ Array ${tmp } = ' )
87132 g.gen_expr (rhs_id)
88- g.writeln (');' )
133+ g.writeln (';' )
134+ g.write ('array__push_many(${amp }' )
135+ gen_expr_lvalue (mut g, lhs_id)
136+ g.writeln (', ${tmp }.data, ${tmp }.len); }' )
89137}
90138
91139// gen_slice_expr emits slice expr output for c.
@@ -94,24 +142,39 @@ fn (mut g FlatGen) gen_slice_expr(node flat.Node, base_id flat.NodeId, base_type
94142 has_start := start_node.kind != .empty
95143 has_end := node.children_count > 2
96144 base_str := g.expr_to_string (base_id)
145+ is_array , is_ptr , _ := array_index_info (base_type)
146+ is_fixed_array , fixed_is_ptr , fixed := fixed_array_index_info (base_type)
97147 start_str := if has_start { g.expr_to_string (g.a.child (& node, 1 )) } else { '0' }
98148 end_str := if has_end {
99149 g.expr_to_string (g.a.child (& node, 2 ))
150+ } else if is_fixed_array {
151+ g.fixed_array_len_value (fixed)
152+ } else if is_array && is_ptr {
153+ '${base_str }->len'
100154 } else {
101155 '${base_str }.len'
102156 }
103157 if base_type is types.String {
104158 g.write ('string__substr(${base_str }, ${start_str }, ${end_str })' )
105- } else if base_type is types.Array {
106- g.write ('array_slice(${base_str }, ${start_str }, ${end_str })' )
159+ } else if is_fixed_array {
160+ c_elem := g.tc.c_type (fixed.elem_type)
161+ data_str := if fixed_is_ptr { '(*${base_str })' } else { base_str }
162+ // Evaluate the slice bounds once so side-effecting expressions such as
163+ // `arr[i++..limit()]` are not run multiple times in the generated C.
164+ start_tmp := g.tmp_name ()
165+ count_tmp := g.tmp_name ()
166+ g.write ('({ int ${start_tmp } = (${start_str }); int ${count_tmp } = (${end_str }) - ${start_tmp }; new_array_from_c_array(${count_tmp }, ${count_tmp }, sizeof(${c_elem }), &${data_str }[${start_tmp }]); })' )
167+ } else if is_array {
168+ arr_str := if is_ptr { '*${base_str }' } else { base_str }
169+ g.write ('array_slice(${arr_str }, ${start_str }, ${end_str })' )
107170 } else {
108171 g.write ('string__substr(${base_str }, ${start_str }, ${end_str })' )
109172 }
110173}
111174
112175// gen_array_method_call emits array method call output for c.
113176fn (mut g FlatGen) gen_array_method_call (node flat.Node, fn_node & flat.Node, arr types.Array) {
114- c_elem := g.tc. c_type (arr.elem_type)
177+ c_elem := g.value_c_type (arr.elem_type)
115178 base_id := g.a.child (fn_node, 0 )
116179 base_node := g.a.nodes[int (base_id)]
117180 is_ptr := if base_node.kind == .ident {
@@ -122,7 +185,10 @@ fn (mut g FlatGen) gen_array_method_call(node flat.Node, fn_node &flat.Node, arr
122185 dot := if is_ptr { '->' } else { '.' }
123186 match fn_node.value {
124187 'clone' {
125- g.write ('array_clone(' )
188+ g.write ('array__clone(' )
189+ if ! is_ptr {
190+ g.write ('&' )
191+ }
126192 g.gen_expr (base_id)
127193 g.write (')' )
128194 }
@@ -226,7 +292,7 @@ fn (mut g FlatGen) gen_array_method_call(node flat.Node, fn_node &flat.Node, arr
226292 g.write (')' )
227293 }
228294 'join' {
229- g.write ('array_string_join (' )
295+ g.write ('Array_string__join (' )
230296 g.gen_expr (base_id)
231297 g.write (', ' )
232298 g.gen_expr (g.a.child (& node, 1 ))
@@ -343,8 +409,8 @@ fn (mut g FlatGen) gen_index_assign(node flat.Node) {
343409 base_type := g.tc.resolve_type (base_id)
344410 clean_base := types.unwrap_pointer (base_type)
345411 if clean_base is types.Map {
346- c_key := g.tc. c_type (clean_base.key_type)
347- c_val := g.tc. c_type (clean_base.value_type)
412+ c_key := g.value_c_type (clean_base.key_type)
413+ c_val := g.value_c_type (clean_base.value_type)
348414 is_ptr := base_type is types.Pointer
349415 if is_ptr {
350416 g.write ('map__set(' )
@@ -386,7 +452,7 @@ fn (mut g FlatGen) gen_index_assign(node flat.Node) {
386452 }
387453 }
388454 if is_array_base {
389- c_elem := g.tc. c_type (arr_type.elem_type)
455+ c_elem := g.value_c_type (arr_type.elem_type)
390456 g.write ('array_set(' )
391457 if base_type is types.Pointer {
392458 g.write ('*' )
0 commit comments