vxx2 / vlib / v3 / transform / or.v
677 lines · 638 sloc · 21.56 KB · 2b81918e62db9ab38787518603a7f93bee80868c
Raw
1module transform
2
3import v3.flat
4import v3.types
5
6// ArrayIndexInfo stores array index info metadata used by transform.
7struct ArrayIndexInfo {
8 base_id flat.NodeId
9 index_id flat.NodeId
10 base_type string
11 value_type string
12}
13
14struct StringSliceInfo {
15 base_id flat.NodeId
16 start_id flat.NodeId
17 end_id flat.NodeId
18 has_end bool
19}
20
21// EnumFromStringInfo stores enum from string info metadata used by transform.
22struct EnumFromStringInfo {
23 enum_type string
24 fields []string
25 arg_id flat.NodeId
26}
27
28// optional_base_type supports optional base type handling for Transformer.
29fn (t &Transformer) optional_base_type(typ string) string {
30 if typ.len > 1 && (typ[0] == `?` || typ[0] == `!`) {
31 return typ[1..]
32 }
33 return typ
34}
35
36// array_index_info supports array index info handling for Transformer.
37fn (mut t Transformer) array_index_info(index_id flat.NodeId) ?ArrayIndexInfo {
38 if int(index_id) < 0 {
39 return none
40 }
41 expr := t.a.nodes[int(index_id)]
42 if expr.kind != .index || expr.children_count < 2 || expr.value == 'range' {
43 return none
44 }
45 base_id := t.a.child(&expr, 0)
46 index_expr_id := t.a.child(&expr, 1)
47 base_type := t.resolve_expr_type(base_id)
48 if !base_type.starts_with('[]') {
49 return none
50 }
51 value_type := t.normalize_type_alias(base_type[2..])
52 if value_type.len == 0 {
53 return none
54 }
55 if t.is_optional_type_name(value_type) {
56 return none
57 }
58 return ArrayIndexInfo{
59 base_id: base_id
60 index_id: index_expr_id
61 base_type: base_type
62 value_type: value_type
63 }
64}
65
66// is_array_index_or_expr reports whether is array index or expr applies in transform.
67fn (mut t Transformer) is_array_index_or_expr(node flat.Node) bool {
68 if node.kind != .or_expr || node.children_count < 2 {
69 return false
70 }
71 _ := t.array_index_info(t.a.child(&node, 0)) or { return false }
72 return true
73}
74
75fn (mut t Transformer) string_slice_info(index_id flat.NodeId) ?StringSliceInfo {
76 if int(index_id) < 0 {
77 return none
78 }
79 expr := t.a.nodes[int(index_id)]
80 if expr.kind != .index || expr.children_count < 2 || expr.value != 'range' {
81 return none
82 }
83 base_id := t.a.child(&expr, 0)
84 base_type := t.resolve_expr_type(base_id)
85 if t.normalize_type_alias(base_type) != 'string' {
86 return none
87 }
88 return StringSliceInfo{
89 base_id: base_id
90 start_id: t.a.child(&expr, 1)
91 end_id: if expr.children_count > 2 { t.a.child(&expr, 2) } else { flat.empty_node }
92 has_end: expr.children_count > 2
93 }
94}
95
96fn (mut t Transformer) is_string_slice_or_expr(node flat.Node) bool {
97 if node.kind != .or_expr || node.children_count < 2 {
98 return false
99 }
100 _ := t.string_slice_info(t.a.child(&node, 0)) or { return false }
101 return true
102}
103
104fn (mut t Transformer) transform_string_slice_or_expr(id flat.NodeId, node flat.Node) flat.NodeId {
105 if node.children_count < 2 {
106 return id
107 }
108 expr_id := t.a.child(&node, 0)
109 body_id := t.a.child(&node, 1)
110 info := t.string_slice_info(expr_id) or { return id }
111 base_expr := t.stable_expr_for_reuse(info.base_id)
112 start_name := t.new_temp('str_start')
113 end_name := t.new_temp('str_end')
114 val_name := t.new_temp('str_slice')
115 outer_pending := t.pending_stmts.clone()
116 t.pending_stmts.clear()
117 start_expr := if int(info.start_id) >= 0 && t.a.nodes[int(info.start_id)].kind != .empty {
118 t.transform_expr(info.start_id)
119 } else {
120 t.make_int_literal(0)
121 }
122 end_expr := if info.has_end {
123 t.transform_expr(info.end_id)
124 } else {
125 t.make_selector(base_expr, 'len', 'int')
126 }
127 mut prelude := []flat.NodeId{}
128 t.drain_pending(mut prelude)
129 prelude << t.make_decl_assign_typed(start_name, start_expr, 'int')
130 prelude << t.make_decl_assign_typed(end_name, end_expr, 'int')
131 prelude << t.make_decl_assign_typed(val_name, t.zero_value_for_type('string'), 'string')
132 start_ident := t.make_ident(start_name)
133 lower_ok := t.make_infix(.ge, start_ident, t.make_int_literal(0))
134 ordered := t.make_infix(.le, t.make_ident(start_name), t.make_ident(end_name))
135 upper_ok := t.make_infix(.le, t.make_ident(end_name), t.make_selector(base_expr, 'len', 'int'))
136 bounds_ok := t.make_infix(.logical_and, t.make_infix(.logical_and, lower_ok, ordered), upper_ok)
137 slice_call := t.make_call_typed('string__substr', arr3(base_expr, t.make_ident(start_name),
138 t.make_ident(end_name)), 'string')
139 then_block := t.make_block(arr1(t.make_assign(t.make_ident(val_name), slice_call)))
140 else_block :=
141 t.make_block(t.lower_or_body_to_stmts(body_id, val_name, 'string', node.value, ''))
142 t.pending_stmts = outer_pending
143 for stmt in prelude {
144 t.pending_stmts << stmt
145 }
146 t.pending_stmts << t.make_if(bounds_ok, then_block, else_block)
147 return t.make_ident(val_name)
148}
149
150// transform_array_index_or_expr transforms transform array index or expr data for transform.
151fn (mut t Transformer) transform_array_index_or_expr(id flat.NodeId, node flat.Node) flat.NodeId {
152 if node.children_count < 2 {
153 return id
154 }
155 expr_id := t.a.child(&node, 0)
156 body_id := t.a.child(&node, 1)
157 info := t.array_index_info(expr_id) or { return id }
158 base_expr := t.stable_expr_for_reuse(info.base_id)
159 index_name := t.new_temp('arr_idx')
160 val_name := t.new_temp('arr_val')
161 outer_pending := t.pending_stmts.clone()
162 t.pending_stmts.clear()
163 index_expr := t.transform_expr(info.index_id)
164 mut prelude := []flat.NodeId{}
165 t.drain_pending(mut prelude)
166 prelude << t.make_decl_assign_typed(index_name, index_expr, 'int')
167 prelude << t.make_decl_assign_typed(val_name, t.zero_value_for_type(info.value_type),
168 info.value_type)
169
170 idx_ident := t.make_ident(index_name)
171 lower_ok := t.make_infix(.ge, idx_ident, t.make_int_literal(0))
172 upper_ok := t.make_infix(.lt, t.make_ident(index_name),
173 t.make_selector(base_expr, 'len', 'int'))
174 found_cond := t.make_infix(.logical_and, lower_ok, upper_ok)
175 index_value := t.make_index(base_expr, t.make_ident(index_name), info.value_type)
176 then_block := t.make_block(arr1(t.make_assign(t.make_ident(val_name), index_value)))
177 else_block := t.make_block(t.lower_or_body_to_stmts(body_id, val_name, info.value_type,
178 node.value, ''))
179 t.pending_stmts = outer_pending
180 for stmt in prelude {
181 t.pending_stmts << stmt
182 }
183 t.pending_stmts << t.make_if(found_cond, then_block, else_block)
184 return t.make_ident(val_name)
185}
186
187// or_body_is_nil supports or body is nil handling for Transformer.
188fn (t &Transformer) or_body_is_nil(body_id flat.NodeId) bool {
189 if int(body_id) < 0 {
190 return false
191 }
192 body := t.a.nodes[int(body_id)]
193 if body.kind == .nil_literal {
194 return true
195 }
196 if body.kind != .block || body.children_count != 1 {
197 return false
198 }
199 stmt_id := t.a.child(&body, 0)
200 stmt := t.a.nodes[int(stmt_id)]
201 if stmt.kind == .expr_stmt && stmt.children_count == 1 {
202 return t.a.nodes[int(t.a.child(&stmt, 0))].kind == .nil_literal
203 }
204 return stmt.kind == .nil_literal
205}
206
207// enum_from_string_info converts enum from string info data for transform.
208fn (t &Transformer) enum_from_string_info(expr_id flat.NodeId) ?EnumFromStringInfo {
209 if int(expr_id) < 0 {
210 return none
211 }
212 expr := t.a.nodes[int(expr_id)]
213 if expr.kind != .call || expr.children_count < 2 {
214 return none
215 }
216 fn_id := t.a.child(&expr, 0)
217 fn_node := t.a.nodes[int(fn_id)]
218 if fn_node.kind != .selector || fn_node.value != 'from_string' || fn_node.children_count == 0 {
219 return none
220 }
221 enum_id := t.a.child(&fn_node, 0)
222 enum_type := t.enum_type_from_node(enum_id) or { return none }
223 fields := t.enum_types[enum_type] or { return none }
224 if fields.len == 0 {
225 return none
226 }
227 return EnumFromStringInfo{
228 enum_type: enum_type
229 fields: fields.clone()
230 arg_id: t.a.child(&expr, 1)
231 }
232}
233
234// enum_type_from_node converts enum type from node data for transform.
235fn (t &Transformer) enum_type_from_node(id flat.NodeId) ?string {
236 if int(id) < 0 {
237 return none
238 }
239 node := t.a.nodes[int(id)]
240 if node.kind == .ident {
241 if node.value in t.enum_types {
242 return node.value
243 }
244 if t.cur_module.len > 0 && t.cur_module != 'main' && t.cur_module != 'builtin' {
245 qname := '${t.cur_module}.${node.value}'
246 if qname in t.enum_types {
247 return qname
248 }
249 }
250 for key, _ in t.enum_types {
251 if key.all_after_last('.') == node.value {
252 return key
253 }
254 }
255 }
256 if node.kind == .selector && node.children_count > 0 {
257 base := t.a.child_node(&node, 0)
258 if base.kind == .ident {
259 qname := '${base.value}.${node.value}'
260 if qname in t.enum_types {
261 return qname
262 }
263 }
264 }
265 return none
266}
267
268// is_enum_from_string_or_expr reports whether is enum from string or expr applies in transform.
269fn (mut t Transformer) is_enum_from_string_or_expr(node flat.Node) bool {
270 if node.kind != .or_expr || node.children_count < 2 {
271 return false
272 }
273 _ := t.enum_from_string_info(t.a.child(&node, 0)) or { return false }
274 return true
275}
276
277// transform_enum_from_string_or_expr supports transform_enum_from_string_or_expr handling.
278fn (mut t Transformer) transform_enum_from_string_or_expr(id flat.NodeId, node flat.Node) flat.NodeId {
279 if node.children_count < 2 {
280 return id
281 }
282 expr_id := t.a.child(&node, 0)
283 body_id := t.a.child(&node, 1)
284 info := t.enum_from_string_info(expr_id) or { return id }
285 str_name := t.new_temp('enum_str')
286 val_name := t.new_temp('enum_val')
287 outer_pending := t.pending_stmts.clone()
288 t.pending_stmts.clear()
289 arg_expr := t.transform_expr(info.arg_id)
290 mut prelude := []flat.NodeId{}
291 t.drain_pending(mut prelude)
292 prelude << t.make_decl_assign_typed(str_name, arg_expr, 'string')
293 prelude << t.make_decl_assign_typed(val_name, t.zero_value_for_type(info.enum_type),
294 info.enum_type)
295
296 mut else_block := t.make_block(t.lower_or_body_to_stmts(body_id, val_name, info.enum_type,
297 node.value, ''))
298 for i := info.fields.len - 1; i >= 0; i-- {
299 cond := t.make_call_typed('string__eq', arr2(t.make_ident(str_name),
300 t.make_string_literal(info.fields[i])), 'bool')
301 assign := t.make_assign(t.make_ident(val_name), t.make_int_literal(i))
302 then_block := t.make_block(arr1(assign))
303 else_block = t.make_if(cond, then_block, else_block)
304 }
305 t.pending_stmts = outer_pending
306 for stmt in prelude {
307 t.pending_stmts << stmt
308 }
309 t.pending_stmts << else_block
310 return t.make_ident(val_name)
311}
312
313// or_expr_types supports or expr types handling for Transformer.
314fn (mut t Transformer) or_expr_types(expr_id flat.NodeId, fallback_type string) (string, string) {
315 expr_node := if int(expr_id) >= 0 && int(expr_id) < t.a.nodes.len {
316 t.a.nodes[int(expr_id)]
317 } else {
318 flat.Node{}
319 }
320 if !isnil(t.tc) {
321 if expr_node.kind == .call {
322 concrete_ret := t.concrete_generic_call_return_type(expr_id, expr_node)
323 if t.is_optional_type_name(concrete_ret) {
324 return concrete_ret, t.optional_base_type(concrete_ret)
325 }
326 call_ret := t.get_call_return_type(expr_id, expr_node)
327 if t.is_optional_type_name(call_ret) {
328 return call_ret, t.optional_base_type(call_ret)
329 }
330 }
331 if typ := t.tc.expr_type(expr_id) {
332 if typ is types.OptionType {
333 base_name := t.value_type_name(typ.base_type)
334 source_name := if base_name == 'int' && typ.base_type is types.Void {
335 '?void'
336 } else {
337 '?${base_name}'
338 }
339 return source_name, base_name
340 }
341 if typ is types.ResultType {
342 base_name := t.value_type_name(typ.base_type)
343 source_name := if base_name == 'int' && typ.base_type is types.Void {
344 '!void'
345 } else {
346 '!${base_name}'
347 }
348 return source_name, base_name
349 }
350 }
351 }
352 mut expr_type := t.node_type(expr_id)
353 if expr_type.len == 0 || expr_type == 'Optional' {
354 if fallback_type.len > 0 && !t.is_optional_type_name(fallback_type) {
355 expr_type = '?${fallback_type}'
356 } else {
357 expr_type = fallback_type
358 }
359 }
360 base_type := t.optional_base_type(expr_type)
361 mut value_type := if base_type.len > 0 { base_type } else { fallback_type }
362 if value_type.len == 0 || value_type == 'void' || value_type == '!' || value_type == '?' {
363 value_type = 'int'
364 }
365 return expr_type, value_type
366}
367
368// value_type_name returns value type name data for Transformer.
369fn (t &Transformer) value_type_name(typ types.Type) string {
370 if typ is types.Void {
371 return 'void'
372 }
373 return typ.name()
374}
375
376// is_optional_type_name reports whether is optional type name applies in transform.
377fn (t &Transformer) is_optional_type_name(typ string) bool {
378 return typ.len > 0 && (typ[0] == `?` || typ[0] == `!`)
379}
380
381// qualify_optional_type supports qualify optional type handling for Transformer.
382fn (t &Transformer) qualify_optional_type(typ string) string {
383 if typ.len < 2 || (typ[0] != `?` && typ[0] != `!`) {
384 return typ
385 }
386 base := typ[1..]
387 if base.contains('.') || base.len == 0 {
388 return typ
389 }
390 qualified := t.qualify_type(base)
391 if qualified != base {
392 return typ[..1] + qualified
393 }
394 return typ
395}
396
397// qualify_type supports qualify type handling for Transformer.
398fn (t &Transformer) qualify_type(name string) string {
399 if name.contains('.') || name.len == 0 {
400 return name
401 }
402 if t.cur_module.len > 0 && t.cur_module != 'main' && t.cur_module != 'builtin' {
403 qname := '${t.cur_module}.${name}'
404 if qname in t.sum_types || qname in t.structs {
405 return qname
406 }
407 }
408 if qualified := t.qualified_types[name] {
409 return qualified
410 }
411 return name
412}
413
414// make_decl_assign_typed builds make decl assign typed data for transform.
415fn (mut t Transformer) make_decl_assign_typed(name string, rhs flat.NodeId, typ string) flat.NodeId {
416 decl := t.make_decl_assign(name, rhs)
417 if typ.len > 0 {
418 t.a.nodes[int(decl)].typ = typ
419 t.set_var_type(name, typ)
420 }
421 return decl
422}
423
424// zero_value_for_type supports zero value for type handling for Transformer.
425fn (mut t Transformer) zero_value_for_type(typ string) flat.NodeId {
426 mut clean := typ
427 if clean.starts_with('&') {
428 return t.a.add(.nil_literal)
429 }
430 if clean.len > 1 && (clean[0] == `?` || clean[0] == `!`) {
431 return t.make_optional_none(clean)
432 }
433 clean = t.normalize_type_alias(clean)
434 if clean.starts_with('fn(') || clean.starts_with('fn (') || clean.starts_with('fn_ptr:') {
435 return t.make_cast(clean, t.make_int_literal(0), clean)
436 }
437 if clean.starts_with('[]') {
438 return t.make_array_init(clean[2..])
439 }
440 if clean.starts_with('map[') {
441 return t.make_map_init(clean)
442 }
443 if t.is_fixed_array_type(clean) {
444 fixed_type := fixed_array_canonical_type(clean)
445 len_text := fixed_array_len_text(fixed_type)
446 if is_decimal_text(len_text) {
447 elem_type := fixed_array_elem_type(fixed_type)
448 mut values := []flat.NodeId{cap: len_text.int()}
449 for _ in 0 .. len_text.int() {
450 values << t.zero_value_for_type(elem_type)
451 }
452 return t.make_array_literal_typed(values, fixed_type)
453 }
454 }
455 if clean == 'string' {
456 return t.make_string_literal('')
457 }
458 if clean == 'bool' {
459 return t.make_bool_literal(false)
460 }
461 if clean in ['f32', 'f64'] {
462 return t.make_float_literal('0.0')
463 }
464 if clean in ['void', ''] {
465 return t.make_int_literal(0)
466 }
467 if clean in ['int', 'i8', 'i16', 'i32', 'i64', 'isize', 'usize', 'u8', 'byte', 'u16', 'u32', 'u64', 'rune', 'char']
468 || clean in t.enum_types {
469 return t.make_int_literal(0)
470 }
471 return t.make_struct_init(clean)
472}
473
474// make_panic_stmt builds make panic stmt data for transform.
475fn (mut t Transformer) make_panic_stmt(message string) flat.NodeId {
476 call := t.make_call('panic', arr1(t.make_string_literal(message)))
477 return t.make_expr_stmt(call)
478}
479
480// make_none_return_stmt builds make none return stmt data for transform.
481fn (mut t Transformer) make_none_return_stmt() flat.NodeId {
482 return t.make_return(t.a.add(.none_expr), t.cur_fn_ret_type)
483}
484
485// make_none_return_stmt_with_err builds make none return stmt with err data for transform.
486fn (mut t Transformer) make_none_return_stmt_with_err(err_source string) flat.NodeId {
487 if err_source.len == 0 {
488 return t.make_none_return_stmt()
489 }
490 err_expr := t.make_selector(t.make_ident(err_source), 'err', 'IError')
491 return t.make_none_return_stmt_with_err_expr(err_expr)
492}
493
494fn (mut t Transformer) make_none_return_stmt_with_err_expr(err_expr flat.NodeId) flat.NodeId {
495 if int(err_expr) < 0 {
496 return t.make_none_return_stmt()
497 }
498 return t.make_return(t.make_optional_none_with_err(t.cur_fn_ret_type, err_expr),
499 t.cur_fn_ret_type)
500}
501
502// lower_or_expr_to_temp converts lower or expr to temp data for transform.
503fn (mut t Transformer) lower_or_expr_to_temp(id flat.NodeId, node flat.Node) flat.NodeId {
504 if node.children_count < 2 {
505 return id
506 }
507 expr_id := t.a.child(&node, 0)
508 body_id := t.a.child(&node, 1)
509 expr_type, value_type := t.or_expr_types(expr_id, node.typ)
510 if !t.is_optional_type_name(expr_type) {
511 return t.transform_expr(expr_id)
512 }
513 is_void := value_type.len == 0 || value_type == 'void'
514
515 opt_tmp := t.new_temp('or_opt')
516 val_tmp := t.new_temp('or_val')
517
518 outer_pending := t.pending_stmts.clone()
519 t.pending_stmts.clear()
520 new_expr := t.transform_expr(expr_id)
521 mut prelude := []flat.NodeId{}
522 t.drain_pending(mut prelude)
523
524 if is_void {
525 prelude << t.make_decl_assign_typed(opt_tmp, new_expr, expr_type)
526 opt_ident := t.make_ident(opt_tmp)
527 not_ok := t.make_prefix(.not, t.make_selector(opt_ident, 'ok', 'bool'))
528 else_block := t.make_block(t.lower_or_body_to_stmts(body_id, '', '', node.value, opt_tmp))
529 if_stmt := t.make_if(not_ok, else_block, t.make_empty())
530 t.pending_stmts = outer_pending
531 for stmt in prelude {
532 t.pending_stmts << stmt
533 }
534 t.pending_stmts << if_stmt
535 return t.make_int_literal(0)
536 }
537
538 prelude << t.make_decl_assign_typed(opt_tmp, new_expr, expr_type)
539 prelude << t.make_decl_assign_typed(val_tmp, t.zero_value_for_type(value_type), value_type)
540
541 opt_ident := t.make_ident(opt_tmp)
542 ok_cond := t.make_selector(opt_ident, 'ok', 'bool')
543 value_expr := t.make_selector(t.make_ident(opt_tmp), 'value', value_type)
544 then_assign := t.make_assign(t.make_ident(val_tmp), value_expr)
545 then_block := t.make_block(arr1(then_assign))
546 else_block := t.make_block(t.lower_or_body_to_stmts(body_id, val_tmp, value_type, node.value,
547 opt_tmp))
548 if_stmt := t.make_if(ok_cond, then_block, else_block)
549 t.pending_stmts = outer_pending
550 for stmt in prelude {
551 t.pending_stmts << stmt
552 }
553 t.pending_stmts << if_stmt
554 return t.make_ident(val_tmp)
555}
556
557// lower_or_body_to_stmts converts lower or body to stmts data for transform.
558fn (mut t Transformer) lower_or_body_to_stmts(body_id flat.NodeId, target_name string, target_type string, mode string, err_source string) []flat.NodeId {
559 err_expr := if err_source.len > 0 {
560 t.make_selector(t.make_ident(err_source), 'err', 'IError')
561 } else {
562 flat.empty_node
563 }
564 return t.lower_or_body_to_stmts_with_err_expr(body_id, target_name, target_type, mode, err_expr)
565}
566
567fn (mut t Transformer) lower_or_body_to_stmts_with_err_expr(body_id flat.NodeId, target_name string, target_type string, mode string, err_expr flat.NodeId) []flat.NodeId {
568 if mode == '!' || mode == '?' {
569 if t.is_optional_type_name(t.cur_fn_ret_type) {
570 return arr1(t.make_none_return_stmt_with_err_expr(err_expr))
571 }
572 return arr1(t.make_panic_stmt('option/result propagation failed'))
573 }
574 if int(body_id) < 0 {
575 return []flat.NodeId{}
576 }
577 body := t.a.nodes[int(body_id)]
578 if body.kind != .block {
579 if body.kind == .none_expr && t.is_optional_type_name(t.cur_fn_ret_type) {
580 return arr1(t.make_none_return_stmt())
581 }
582 if target_name.len == 0 {
583 value := t.transform_expr(body_id)
584 mut result := []flat.NodeId{}
585 t.drain_pending(mut result)
586 if t.node_type(body_id) != 'void' {
587 result << t.make_expr_stmt(value)
588 }
589 return result
590 }
591 return arr1(t.make_assign(t.make_ident(target_name), t.transform_expr(body_id)))
592 }
593 mut result := []flat.NodeId{}
594 if body.children_count == 0 {
595 return result
596 }
597 // The or-body is its own scope: `err` (and any locals it declares) are bound only
598 // for its lowering and restored afterwards, so the previous binding (e.g. an outer
599 // `err := 1`) survives and a subsequent `${err}` is not mis-typed as `IError`.
600 // Mirrors transform_if_guard_else_block.
601 saved_var_types := t.var_types.clone()
602 t.set_var_type('err', 'IError')
603 err_value := if int(err_expr) >= 0 {
604 err_expr
605 } else {
606 t.make_struct_init('IError')
607 }
608 result << t.make_decl_assign_typed('err', err_value, 'IError')
609 for i in 0 .. body.children_count {
610 child_id := t.a.child(&body, i)
611 child := t.a.nodes[int(child_id)]
612 is_last := i == body.children_count - 1
613 if is_last && child.kind == .expr_stmt && child.children_count > 0 {
614 inner_id := t.a.child(&child, 0)
615 inner := t.a.nodes[int(inner_id)]
616 if inner.kind == .call && t.is_noreturn_call(inner) {
617 expanded := t.transform_stmt(child_id)
618 t.drain_pending(mut result)
619 for eid in expanded {
620 result << eid
621 }
622 } else if inner.kind == .call && t.is_error_call(inner)
623 && t.is_optional_type_name(t.cur_fn_ret_type) {
624 result << t.make_return(inner_id, t.cur_fn_ret_type)
625 } else if inner.kind == .none_expr && t.is_optional_type_name(t.cur_fn_ret_type) {
626 result << t.make_none_return_stmt()
627 } else if t.node_type(inner_id) == 'void' {
628 expanded := t.transform_stmt(child_id)
629 t.drain_pending(mut result)
630 for eid in expanded {
631 result << eid
632 }
633 } else if target_name.len == 0 {
634 expanded := t.transform_stmt(child_id)
635 t.drain_pending(mut result)
636 for eid in expanded {
637 result << eid
638 }
639 } else {
640 value := if target_type in t.sum_types
641 || t.resolve_sum_name(target_type) in t.sum_types {
642 t.wrap_sum_value(inner_id, target_type)
643 } else {
644 t.transform_expr_for_type(inner_id, target_type)
645 }
646 t.drain_pending(mut result)
647 result << t.make_assign(t.make_ident(target_name), value)
648 }
649 } else {
650 expanded := t.transform_stmt(child_id)
651 t.drain_pending(mut result)
652 for eid in expanded {
653 result << eid
654 }
655 }
656 }
657 _ = target_type
658 t.var_types = saved_var_types
659 return result
660}
661
662fn (t &Transformer) is_error_call(node flat.Node) bool {
663 if node.kind != .call || node.children_count == 0 {
664 return false
665 }
666 fn_node := t.a.child_node(&node, 0)
667 return fn_node.value == 'error' || fn_node.value == 'error_with_code'
668}
669
670// is_noreturn_call reports whether is noreturn call applies in transform.
671fn (t &Transformer) is_noreturn_call(node flat.Node) bool {
672 if node.kind != .call || node.children_count == 0 {
673 return false
674 }
675 fn_node := t.a.child_node(&node, 0)
676 return fn_node.value in ['panic', 'exit']
677}
678