vq / vlib / v3 / eval / eval.v
6132 lines · 5828 sloc · 154.33 KB
Raw

<
1module eval
2
3import os
4import strconv
5import time
6import v3.flat
7import v3.parser
8import v3.pref
9
10pub type Value = ArrayValue
11 | EnumValue
12 | FnValue
13 | MapValue
14 | ModuleValue
15 | RangeValue
16 | StructValue
17 | SumValue
18 | TupleValue
19 | TypeValue
20 | VoidValue
21 | bool
22 | f64
23 | i64
24 | string
25
26pub struct ArrayValue {
27pub mut:
28 elem_type_name string
29 values []Value
30}
31
32pub struct EnumValue {
33pub:
34 type_name string
35 value i64
36}
37
38pub struct FnValue {
39 node flat.NodeId
40 module_name string
41 file_name string
42 captures map[string]Value
43 capture_types map[string]string
44}
45
46pub struct MapEntry {
47pub:
48 key Value
49pub mut:
50 value Value
51}
52
53pub struct MapValue {
54pub mut:
55 key_type_name string
56 value_type_name string
57 default_value Value
58 entries []MapEntry
59}
60
61pub struct ModuleValue {
62pub:
63 name string
64}
65
66pub struct RangeValue {
67pub:
68 start i64
69 end i64
70 inclusive bool
71}
72
73pub struct StructValue {
74pub:
75 type_name string
76pub mut:
77 fields map[string]Value
78}
79
80pub struct SumValue {
81pub:
82 type_name string
83 variant_name string
84pub mut:
85 payload Value
86}
87
88pub struct TupleValue {
89pub:
90 values []Value
91}
92
93pub struct TypeValue {
94pub:
95 name string
96}
97
98pub struct VoidValue {}
99
100struct FunctionDef {
101 node flat.NodeId
102 name string
103 module_name string
104 file_name string
105}
106
107struct ConstEntry {
108 node flat.NodeId
109 module_name string
110 file_name string
111mut:
112 cached bool
113 evaluating bool
114 value Value
115}
116
117struct GlobalEntry {
118 name string
119 typ string
120 default_node flat.NodeId
121 module_name string
122 file_name string
123}
124
125struct EnumInitEntry {
126 node flat.NodeId
127 module_name string
128 file_name string
129}
130
131struct TopLevelStmt {
132 node flat.NodeId
133 module_name string
134 file_name string
135}
136
137struct StructInfo {
138 module_name string
139 name string
140mut:
141 fields []FieldInfo
142}
143
144struct TypeAliasInfo {
145 module_name string
146 target string
147}
148
149struct FieldInfo {
150 name string
151 typ string
152 default_node flat.NodeId
153 module_name string
154 file_name string
155}
156
157struct ScopeFrame {
158mut:
159 vars map[string]Value
160 types map[string]string
161 defer_stmts []flat.NodeId
162}
163
164struct CallFrame {
165 module_name string
166 file_name string
167 fn_name string
168 return_type string
169 scope_idx int = -1
170}
171
172struct MaybeValue {
173 found bool
174 value Value
175}
176
177struct SmartcastBinding {
178 name string
179 value Value
180 type_name string
181}
182
183struct CallResult {
184 values []Value
185 mutated_args map[int]Value
186 fn_value_changed bool
187 fn_value FnValue
188}
189
190struct MethodCallResult {
191 value Value
192 receiver_changed bool
193 receiver Value
194 mutated_args map[int]Value
195}
196
197struct LvalueStep {
198 kind flat.NodeKind
199 container Value
200 index Value
201 field_name string
202}
203
204struct ResolvedLvalue {
205mut:
206 signal FlowSignal
207 root_id flat.NodeId
208 value Value
209 steps []LvalueStep
210}
211
212struct InfixOperatorCallInfo {
213 target FunctionDef
214 reverse bool
215 negate bool
216}
217
218enum FlowKind {
219 normal
220 break_
221 continue_
222 return_
223}
224
225struct FlowSignal {
226 kind FlowKind
227 label string
228 values []Value
229 mut_lvalues map[int]ResolvedLvalue
230}
231
232// Eval interprets v3 flat AST nodes directly for a practical subset of V.
233pub struct Eval {
234pub mut:
235 capture_output bool
236 prefs pref.Preferences
237mut:
238 a &flat.FlatAst = unsafe { nil }
239 stdout_data string
240 stderr_data string
241 functions map[string]map[string]FunctionDef
242 consts map[string]map[string]ConstEntry
243 globals map[string]map[string]Value
244 global_types map[string]map[string]string
245 global_inits []GlobalEntry
246 enum_inits []EnumInitEntry
247 implicit_main []TopLevelStmt
248 structs map[string]StructInfo
249 enum_fields map[string][]string
250 sum_types map[string][]string
251 type_aliases map[string]TypeAliasInfo
252 type_names map[string]map[string]bool
253 module_imports map[string][]string
254 module_order []string
255 file_import_alias map[string]map[string]string
256 modules map[string]bool
257 scopes []ScopeFrame
258 call_stack []CallFrame
259}
260
261// new returns a new evaluator configured for direct execution.
262pub fn new(prefs_ &pref.Preferences) Eval {
263 return Eval{
264 prefs: *prefs_
265 }
266}
267
268// create returns a capturing evaluator convenient for tests.
269pub fn create() Eval {
270 return Eval{
271 capture_output: true
272 prefs: pref.new_preferences()
273 }
274}
275
276// stdout returns the captured stdout stream.
277pub fn (e &Eval) stdout() string {
278 return e.stdout_data
279}
280
281// stderr returns the captured stderr stream.
282pub fn (e &Eval) stderr() string {
283 return e.stderr_data
284}
285
286// run_text parses and executes a single V source string.
287pub fn (mut e Eval) run_text(code string) ![]Value {
288 tmp_file := os.join_path(os.temp_dir(), 'v3_eval_${os.getpid()}_${time.now().unix_micro()}.v')
289 os.write_file(tmp_file, code)!
290 defer {
291 os.rm(tmp_file) or {}
292 }
293 mut p := parser.Parser.new(&e.prefs)
294 p.parse_into(tmp_file)
295 return e.run_files(p.a)
296}
297
298// run_files executes parsed flat AST files and invokes `main.main`.
299pub fn (mut e Eval) run_files(a &flat.FlatAst) ![]Value {
300 e.reset(a)
301 e.register_files()!
302 e.run_inits()!
303 if e.has_main_function() {
304 return e.call_function('main', 'main', []Value{})!.values
305 }
306 return e.run_implicit_main()
307}
308
309fn void_value() Value {
310 return VoidValue{}
311}
312
313fn normal_flow() FlowSignal {
314 return FlowSignal{
315 kind: .normal
316 }
317}
318
319fn value_flow(value Value) FlowSignal {
320 return FlowSignal{
321 values: [value]
322 }
323}
324
325fn (mut e Eval) reset(a &flat.FlatAst) {
326 e.a = unsafe { a }
327 e.stdout_data = ''
328 e.stderr_data = ''
329 e.functions = map[string]map[string]FunctionDef{}
330 e.consts = map[string]map[string]ConstEntry{}
331 e.globals = map[string]map[string]Value{}
332 e.global_types = map[string]map[string]string{}
333 e.global_inits = []GlobalEntry{}
334 e.enum_inits = []EnumInitEntry{}
335 e.implicit_main = []TopLevelStmt{}
336 e.structs = map[string]StructInfo{}
337 e.enum_fields = map[string][]string{}
338 e.sum_types = map[string][]string{}
339 e.type_aliases = map[string]TypeAliasInfo{}
340 e.type_names = map[string]map[string]bool{}
341 e.module_imports = map[string][]string{}
342 e.module_order = []string{}
343 e.file_import_alias = map[string]map[string]string{}
344 e.modules = map[string]bool{}
345 e.scopes = []ScopeFrame{}
346 e.call_stack = []CallFrame{}
347}
348
349fn (e &Eval) node(id flat.NodeId) &flat.Node {
350 return e.a.node(id)
351}
352
353fn (e &Eval) child(node &flat.Node, index int) flat.NodeId {
354 return e.a.child(node, index)
355}
356
357fn (e &Eval) child_node(node &flat.Node, index int) &flat.Node {
358 return e.a.child_node(node, index)
359}
360
361fn (e &Eval) children(node &flat.Node) []flat.NodeId {
362 return e.a.children_of(node)
363}
364
365fn (mut e Eval) ensure_module_maps(module_name string) {
366 if module_name !in e.functions {
367 e.functions[module_name] = map[string]FunctionDef{}
368 }
369 if module_name !in e.consts {
370 e.consts[module_name] = map[string]ConstEntry{}
371 }
372 if module_name !in e.globals {
373 e.globals[module_name] = map[string]Value{}
374 }
375 if module_name !in e.global_types {
376 e.global_types[module_name] = map[string]string{}
377 }
378 if module_name !in e.type_names {
379 e.type_names[module_name] = map[string]bool{}
380 }
381}
382
383fn (e &Eval) top_level_registration_children(node &flat.Node) []flat.NodeId {
384 mut ids := []flat.NodeId{}
385 for child_id in e.children(node) {
386 child := e.node(child_id)
387 if child.kind == .block {
388 ids << e.top_level_registration_children(child)
389 continue
390 }
391 ids << child_id
392 }
393 return ids
394}
395
396fn (e &Eval) has_main_function() bool {
397 return 'main' in e.functions && 'main' in e.functions['main']
398}
399
400fn is_top_level_declaration_kind(kind flat.NodeKind) bool {
401 match kind {
402 .empty, .module_decl, .import_decl, .directive, .fn_decl, .c_fn_decl, .struct_decl,
403 .field_decl, .global_decl, .const_decl, .const_field, .enum_decl, .enum_field, .type_decl,
404 .interface_decl, .interface_field, .param, .comptime_if, .comptime_for {
405 return true
406 }
407 else {
408 return false
409 }
410 }
411}
412
413fn (mut e Eval) register_implicit_main_stmt(module_name string, file_name string, id flat.NodeId, node &flat.Node) {
414 if module_name != 'main' || is_top_level_declaration_kind(node.kind) {
415 return
416 }
417 e.implicit_main << TopLevelStmt{
418 node: id
419 module_name: module_name
420 file_name: file_name
421 }
422}
423
424fn (mut e Eval) register_files() ! {
425 for file_id, file_node in e.a.nodes {
426 if file_node.kind != .file || file_node.children_count == 0 {
427 continue
428 }
429 file_name := file_node.value
430 top_level_children := e.top_level_registration_children(&file_node)
431 mut module_name := 'main'
432 for child_id in top_level_children {
433 child := e.node(child_id)
434 if child.kind == .module_decl {
435 module_name = child.value
436 break
437 }
438 }
439 if module_name !in e.modules {
440 e.module_order << module_name
441 }
442 e.modules[module_name] = true
443 e.ensure_module_maps(module_name)
444 if module_name !in e.module_imports {
445 e.module_imports[module_name] = []string{}
446 }
447 mut import_aliases := map[string]string{}
448 for child_id in top_level_children {
449 child := e.node(child_id)
450 if child.kind != .import_decl {
451 continue
452 }
453 imported_module := child.value.all_after_last('.')
454 if imported_module.len > 0 && imported_module != module_name
455 && imported_module !in e.module_imports[module_name] {
456 e.module_imports[module_name] << imported_module
457 }
458 import_aliases[child.typ] = imported_module
459 import_aliases[imported_module] = imported_module
460 }
461 e.file_import_alias[file_name] = import_aliases.clone()
462 for child_id in top_level_children {
463 child := e.node(child_id)
464 match child.kind {
465 .import_decl {}
466 .const_decl {
467 for field_id in e.children(child) {
468 field := e.node(field_id)
469 if field.kind != .const_field {
470 continue
471 }
472 e.consts[module_name][field.value] = ConstEntry{
473 node: field_id
474 module_name: module_name
475 file_name: file_name
476 value: void_value()
477 }
478 }
479 }
480 .global_decl {
481 for field_id in e.children(child) {
482 field := e.node(field_id)
483 if field.kind != .field_decl {
484 continue
485 }
486 e.global_inits << GlobalEntry{
487 name: field.value
488 typ: field.typ
489 default_node: if field.children_count > 0 {
490 e.child(field, 0)
491 } else {
492 flat.empty_node
493 }
494 module_name: module_name
495 file_name: file_name
496 }
497 e.global_types[module_name][field.value] = e.qualify_nested_type_name(module_name,
498 field.typ)
499 }
500 }
501 .enum_decl {
502 e.type_names[module_name][child.value] = true
503 enum_name := e.qualify_type_name(module_name, child.value)
504 mut enum_fields := []string{}
505 for field_id in e.children(child) {
506 field := e.node(field_id)
507 if field.kind != .enum_field {
508 continue
509 }
510 enum_fields << field.value
511 }
512 e.enum_fields[enum_name] = enum_fields
513 if module_name in ['main', 'builtin'] {
514 e.enum_fields[child.value] = enum_fields
515 }
516 e.enum_inits << EnumInitEntry{
517 node: child_id
518 module_name: module_name
519 file_name: file_name
520 }
521 }
522 .fn_decl {
523 e.register_function(module_name, file_name, child_id, child)
524 }
525 .struct_decl {
526 e.type_names[module_name][child.value] = true
527 mut fields := []FieldInfo{}
528 for field_id in e.children(child) {
529 field := e.node(field_id)
530 if field.kind == .field_decl {
531 fields << FieldInfo{
532 name: field.value
533 typ: field.typ
534 default_node: if field.children_count > 0 {
535 e.child(field, 0)
536 } else {
537 flat.empty_node
538 }
539 module_name: module_name
540 file_name: file_name
541 }
542 }
543 }
544 info := StructInfo{
545 module_name: module_name
546 name: child.value
547 fields: fields
548 }
549 qualified_name := e.qualify_type_name(module_name, child.value)
550 e.structs[qualified_name] = info
551 if module_name in ['main', 'builtin'] {
552 e.structs[child.value] = info
553 }
554 }
555 .type_decl {
556 e.type_names[module_name][child.value] = true
557 if child.children_count > 0 {
558 mut variants := []string{}
559 for variant_id in e.children(child) {
560 variant := e.node(variant_id)
561 variants << e.qualify_type_name(module_name, variant.value)
562 }
563 qualified_name := e.qualify_type_name(module_name, child.value)
564 e.sum_types[qualified_name] = variants
565 if module_name in ['main', 'builtin'] {
566 e.sum_types[child.value] = variants
567 }
568 } else if child.typ.len > 0 {
569 info := TypeAliasInfo{
570 module_name: module_name
571 target: child.typ
572 }
573 qualified_name := e.qualify_type_name(module_name, child.value)
574 e.type_aliases[qualified_name] = info
575 if module_name in ['main', 'builtin'] {
576 e.type_aliases[child.value] = info
577 }
578 }
579 }
580 else {
581 e.register_implicit_main_stmt(module_name, file_name, child_id, child)
582 }
583 }
584 }
585 _ = file_id
586 }
587 e.evaluate_enum_inits()!
588 e.evaluate_global_inits()!
589 if !e.has_main_function() && e.implicit_main.len == 0 {
590 return error('v3.eval: missing main.main entry point')
591 }
592}
593
594fn (mut e Eval) evaluate_enum_inits() ! {
595 for entry in e.enum_inits {
596 node := e.node(entry.node)
597 mut next_value := if node.typ == 'flag' { i64(1) } else { i64(0) }
598 for field_id in e.children(node) {
599 field := e.node(field_id)
600 if field.kind != .enum_field {
601 continue
602 }
603 value := if field.children_count > 0 {
604 e.value_as_int(e.eval_expr_in_module(e.child(field, 0), entry.module_name,
605 entry.file_name, '<enum ${node.value}.${field.value}>')!)!
606 } else {
607 next_value
608 }
609 e.consts[entry.module_name][field.value] = ConstEntry{
610 node: field_id
611 module_name: entry.module_name
612 file_name: entry.file_name
613 cached: true
614 value: Value(value)
615 }
616 e.consts[entry.module_name]['${node.value}.${field.value}'] = ConstEntry{
617 node: field_id
618 module_name: entry.module_name
619 file_name: entry.file_name
620 cached: true
621 value: Value(value)
622 }
623 next_value = if node.typ == 'flag' {
624 if value <= 0 { i64(1) } else { value * 2 }
625 } else {
626 value + 1
627 }
628 }
629 }
630}
631
632fn (mut e Eval) run_implicit_main() ![]Value {
633 e.open_scope()
634 scope_idx := e.scopes.len - 1
635 mut frame := CallFrame{
636 module_name: 'main'
637 file_name: if e.implicit_main.len > 0 { e.implicit_main[0].file_name } else { '' }
638 fn_name: 'main'
639 return_type: 'void'
640 scope_idx: scope_idx
641 }
642 e.call_stack << frame
643 mut values := [void_value()]
644 mut escaped := normal_flow()
645 for stmt in e.implicit_main {
646 frame = CallFrame{
647 module_name: stmt.module_name
648 file_name: stmt.file_name
649 fn_name: 'main'
650 return_type: 'void'
651 scope_idx: scope_idx
652 }
653 e.call_stack[e.call_stack.len - 1] = frame
654 signal := e.exec_stmt(stmt.node)!
655 if signal.kind == .return_ {
656 values = flow_values_or_void(signal.values)
657 break
658 }
659 if signal.kind != .normal {
660 escaped = signal
661 break
662 }
663 }
664 e.run_deferred_stmts()!
665 e.close_scope()!
666 e.call_stack.delete(e.call_stack.len - 1)
667 if escaped.kind != .normal {
668 return error('v3.eval: unexpected `${escaped.kind}` escaped implicit main')
669 }
670 return values
671}
672
673fn (mut e Eval) evaluate_global_inits() ! {
674 mut entries_by_module := map[string][]GlobalEntry{}
675 for entry in e.global_inits {
676 mut entries := entries_by_module[entry.module_name]
677 entries << entry
678 entries_by_module[entry.module_name] = entries
679 }
680 mut visited := map[string]bool{}
681 mut visiting := map[string]bool{}
682 e.evaluate_module_global_inits('main', entries_by_module, mut visited, mut visiting)!
683 for module_name in e.module_order {
684 e.evaluate_module_global_inits(module_name, entries_by_module, mut visited, mut visiting)!
685 }
686}
687
688fn (mut e Eval) evaluate_module_global_inits(module_name string, entries_by_module map[string][]GlobalEntry, mut visited map[string]bool, mut visiting map[string]bool) ! {
689 if module_name in visited {
690 return
691 }
692 if module_name in visiting {
693 return
694 }
695 visiting[module_name] = true
696 if module_name in e.module_imports {
697 for imported_module in e.module_imports[module_name] {
698 e.evaluate_module_global_inits(imported_module, entries_by_module, mut visited, mut
699 visiting)!
700 }
701 }
702 visiting.delete(module_name)
703 visited[module_name] = true
704 if module_name !in entries_by_module {
705 return
706 }
707 for entry in entries_by_module[module_name] {
708 e.evaluate_global_init(entry)!
709 }
710}
711
712fn (mut e Eval) evaluate_global_init(entry GlobalEntry) ! {
713 e.call_stack << CallFrame{
714 module_name: entry.module_name
715 file_name: entry.file_name
716 fn_name: '<global ${entry.name}>'
717 }
718 value := if int(entry.default_node) >= 0 {
719 e.eval_expr(entry.default_node)!
720 } else {
721 e.zero_value_for_type_name_in_module(entry.typ, entry.module_name)
722 }
723 e.call_stack.delete(e.call_stack.len - 1)
724 e.globals[entry.module_name][entry.name] = e.adapt_value_to_type_name(value, entry.typ)
725}
726
727fn (mut e Eval) eval_expr_in_module(id flat.NodeId, module_name string, file_name string, label string) !Value {
728 e.call_stack << CallFrame{
729 module_name: module_name
730 file_name: file_name
731 fn_name: label
732 }
733 defer {
734 e.call_stack.delete(e.call_stack.len - 1)
735 }
736 return e.eval_expr(id)
737}
738
739fn (mut e Eval) register_function(module_name string, file_name string, id flat.NodeId, node &flat.Node) {
740 def := FunctionDef{
741 node: id
742 name: node.value
743 module_name: module_name
744 file_name: file_name
745 }
746 e.functions[module_name][node.value] = def
747 if module_name != 'main' && module_name != 'builtin' {
748 e.functions[module_name]['${module_name}.${node.value}'] = def
749 }
750 if node.value.contains('.') {
751 short := node.value.all_after_last('.')
752 receiver := node.value.all_before_last('.').all_after_last('.')
753 e.functions[module_name]['${receiver}.${short}'] = def
754 }
755}
756
757fn (mut e Eval) run_inits() ! {
758 mut visited := map[string]bool{}
759 mut visiting := map[string]bool{}
760 e.run_module_init('main', mut visited, mut visiting)!
761 for module_name in e.module_order {
762 e.run_module_init(module_name, mut visited, mut visiting)!
763 }
764}
765
766fn (mut e Eval) run_module_init(module_name string, mut visited map[string]bool, mut visiting map[string]bool) ! {
767 if module_name in visited {
768 return
769 }
770 if module_name in visiting {
771 return
772 }
773 visiting[module_name] = true
774 if module_name in e.module_imports {
775 for imported_module in e.module_imports[module_name] {
776 e.run_module_init(imported_module, mut visited, mut visiting)!
777 }
778 }
779 visiting.delete(module_name)
780 visited[module_name] = true
781 if module_name in e.functions && 'init' in e.functions[module_name] {
782 e.call_function(module_name, 'init', []Value{})!
783 }
784}
785
786fn (mut e Eval) open_scope() {
787 e.scopes << ScopeFrame{
788 vars: map[string]Value{}
789 types: map[string]string{}
790 defer_stmts: []flat.NodeId{}
791 }
792}
793
794fn (mut e Eval) close_scope() ! {
795 if e.scopes.len > 0 {
796 e.run_deferred_stmts()!
797 e.scopes.delete(e.scopes.len - 1)
798 }
799}
800
801fn (mut e Eval) declare_var(name string, value Value) {
802 e.declare_var_typed(name, value, '')
803}
804
805fn (mut e Eval) declare_var_typed(name string, value Value, type_name string) {
806 if name == '_' {
807 return
808 }
809 if e.scopes.len == 0 {
810 e.open_scope()
811 }
812 e.scopes[e.scopes.len - 1].vars[name] = value
813 normalized := e.normalize_type_name(type_name)
814 if normalized.len > 0 {
815 e.scopes[e.scopes.len - 1].types[name] = normalized
816 }
817}
818
819fn (mut e Eval) set_var(name string, value Value) ! {
820 if name == '_' {
821 return
822 }
823 for i := e.scopes.len - 1; i >= 0; i-- {
824 if name in e.scopes[i].vars {
825 e.scopes[i].vars[name] = value
826 return
827 }
828 }
829 module_name := e.current_module_name()
830 if module_name in e.globals && name in e.globals[module_name] {
831 e.globals[module_name][name] = value
832 return
833 }
834 return e.unknown_variable_error(name)
835}
836
837fn (mut e Eval) set_var_type(name string, type_name string) {
838 normalized := e.normalize_type_name(type_name)
839 if normalized.len == 0 {
840 return
841 }
842 for i := e.scopes.len - 1; i >= 0; i-- {
843 if name in e.scopes[i].vars {
844 e.scopes[i].types[name] = normalized
845 return
846 }
847 }
848}
849
850fn (e &Eval) lookup_var(name string) MaybeValue {
851 for i := e.scopes.len - 1; i >= 0; i-- {
852 if name in e.scopes[i].vars {
853 return MaybeValue{
854 found: true
855 value: e.scopes[i].vars[name] or { void_value() }
856 }
857 }
858 }
859 module_name := e.current_module_name()
860 if module_name in e.globals && name in e.globals[module_name] {
861 return MaybeValue{
862 found: true
863 value: e.globals[module_name][name] or { void_value() }
864 }
865 }
866 return MaybeValue{}
867}
868
869fn (e &Eval) lookup_var_type(name string) ?string {
870 for i := e.scopes.len - 1; i >= 0; i-- {
871 if name in e.scopes[i].types {
872 return e.scopes[i].types[name]
873 }
874 }
875 module_name := e.current_module_name()
876 if module_name in e.global_types && name in e.global_types[module_name] {
877 return e.global_types[module_name][name]
878 }
879 return none
880}
881
882fn (e &Eval) current_module_name() string {
883 if e.call_stack.len == 0 {
884 return 'main'
885 }
886 return e.call_stack[e.call_stack.len - 1].module_name
887}
888
889fn (e &Eval) current_file_name() string {
890 if e.call_stack.len == 0 {
891 return ''
892 }
893 return e.call_stack[e.call_stack.len - 1].file_name
894}
895
896fn (e &Eval) current_function_label() string {
897 if e.call_stack.len == 0 {
898 return '<top-level>'
899 }
900 frame := e.call_stack[e.call_stack.len - 1]
901 return '${frame.module_name}.${frame.fn_name}'
902}
903
904fn (e &Eval) call_stack_trace() string {
905 return e.call_stack.map('${it.module_name}.${it.fn_name}').join(' -> ')
906}
907
908fn (e &Eval) unknown_variable_error(name string) IError {
909 return error('v3.eval: unknown variable `${name}` in `${e.current_function_label()}` stack `${e.call_stack_trace()}`')
910}
911
912fn (mut e Eval) call_function(module_name string, fn_name string, args []Value) !CallResult {
913 builtin := e.maybe_call_builtin(module_name, fn_name, args)!
914 if builtin.found {
915 return CallResult{
916 values: [builtin.value]
917 }
918 }
919 target_module := if module_name == '' { e.current_module_name() } else { module_name }
920 if target_module !in e.functions {
921 return error('v3.eval: unknown module `${target_module}`')
922 }
923 if fn_name !in e.functions[target_module] {
924 return error('v3.eval: unknown function `${target_module}.${fn_name}`')
925 }
926 def := e.functions[target_module][fn_name]
927 node := e.node(def.node)
928 mut params := []flat.NodeId{}
929 mut body_start := 0
930 for child_id in e.children(node) {
931 child := e.node(child_id)
932 if child.kind == .param {
933 params << child_id
934 body_start++
935 continue
936 }
937 break
938 }
939 min_args := e.minimum_arg_count(params)
940 if args.len < min_args {
941 return error('v3.eval: `${target_module}.${fn_name}` expected ${min_args} arguments, got ${args.len}')
942 }
943 e.open_scope()
944 e.call_stack << CallFrame{
945 module_name: target_module
946 file_name: def.file_name
947 fn_name: fn_name
948 return_type: node.typ
949 scope_idx: e.scopes.len - 1
950 }
951 e.bind_call_params(params, args)!
952 mut body_ids := e.children(node)
953 if body_start > 0 {
954 body_ids = body_ids[body_start..].clone()
955 }
956 signal := e.exec_stmts(body_ids)!
957 e.run_deferred_stmts()!
958 mutated_args := e.collect_mutated_param_args(params, args)
959 adapted_values := if signal.kind == .return_ {
960 e.adapt_return_values(signal.values, node.typ)
961 } else {
962 []Value{}
963 }
964 e.close_scope()!
965 e.call_stack.delete(e.call_stack.len - 1)
966 if signal.kind == .return_ {
967 return CallResult{
968 values: adapted_values
969 mutated_args: mutated_args
970 }
971 }
972 if signal.kind != .normal {
973 return error('v3.eval: unexpected `${signal.kind}` escaped `${target_module}.${fn_name}`')
974 }
975 return CallResult{
976 values: [void_value()]
977 mutated_args: mutated_args
978 }
979}
980
981fn (mut e Eval) exec_stmts(stmts []flat.NodeId) !FlowSignal {
982 mut i := 0
983 for i < stmts.len {
984 stmt_id := stmts[i]
985 if int(stmt_id) >= 0 {
986 node := e.node(stmt_id)
987 if node.kind == .label_stmt && i + 1 < stmts.len {
988 next_id := stmts[i + 1]
989 if int(next_id) >= 0 {
990 next_node := e.node(next_id)
991 if next_node.kind == .for_stmt {
992 signal := e.exec_for(next_node, node.value)!
993 if signal.kind != .normal {
994 return signal
995 }
996 i += 2
997 continue
998 }
999 if next_node.kind == .for_in_stmt {
1000 signal := e.exec_for_in(next_node, node.value)!
1001 if signal.kind != .normal {
1002 return signal
1003 }
1004 i += 2
1005 continue
1006 }
1007 }
1008 }
1009 }
1010 signal := e.exec_stmt(stmt_id)!
1011 if signal.kind != .normal {
1012 return signal
1013 }
1014 i++
1015 }
1016 return normal_flow()
1017}
1018
1019fn (mut e Eval) exec_block(node &flat.Node) !FlowSignal {
1020 e.open_scope()
1021 signal := e.exec_stmts(e.children(node))!
1022 e.close_scope()!
1023 return signal
1024}
1025
1026fn (mut e Eval) exec_stmt(id flat.NodeId) !FlowSignal {
1027 if int(id) < 0 {
1028 return normal_flow()
1029 }
1030 node := e.node(id)
1031 match node.kind {
1032 .block {
1033 return e.exec_block(node)
1034 }
1035 .expr_stmt {
1036 if node.children_count > 0 {
1037 expr_id := e.child(node, 0)
1038 expr := e.node(expr_id)
1039 if expr.kind == .infix && expr.op == .left_shift {
1040 return e.exec_array_append(expr)
1041 } else {
1042 signal := e.eval_expr_flow(expr_id)!
1043 if signal.kind != .normal {
1044 return signal
1045 }
1046 }
1047 }
1048 return normal_flow()
1049 }
1050 .decl_assign {
1051 return e.exec_assign(node, true)
1052 }
1053 .assign, .selector_assign, .index_assign {
1054 return e.exec_assign(node, false)
1055 }
1056 .return_stmt {
1057 mut values := []Value{}
1058 return_type := e.current_return_type()
1059 return_types := split_multi_return_types(return_type)
1060 child_count := node.children_count
1061 mut child_index := 0
1062 for child_id in e.children(node) {
1063 expected_type := return_child_expected_type(return_type, return_types, child_index,
1064 child_count)
1065 signal := e.eval_expr_flow_expected(child_id, expected_type)!
1066 if signal.kind != .normal {
1067 return signal
1068 }
1069 expr_values := flow_values_or_void(signal.values)
1070 if expr_values.len > 1 {
1071 values << expr_values
1072 continue
1073 }
1074 value := expr_values[0]
1075 if value is TupleValue {
1076 values << value.values
1077 } else {
1078 values << value
1079 }
1080 child_index++
1081 }
1082 if values.len == 0 {
1083 values << void_value()
1084 }
1085 return FlowSignal{
1086 kind: .return_
1087 values: values
1088 }
1089 }
1090 .if_expr {
1091 return e.exec_if(node)
1092 }
1093 .match_stmt {
1094 return e.exec_match(node)
1095 }
1096 .for_stmt {
1097 return e.exec_for(node, '')
1098 }
1099 .for_in_stmt {
1100 return e.exec_for_in(node, '')
1101 }
1102 .break_stmt {
1103 return FlowSignal{
1104 kind: .break_
1105 label: node.value
1106 }
1107 }
1108 .continue_stmt {
1109 return FlowSignal{
1110 kind: .continue_
1111 label: node.value
1112 }
1113 }
1114 .assert_stmt {
1115 cond_signal := e.eval_expr_flow(e.child(node, 0))!
1116 if cond_signal.kind != .normal {
1117 return cond_signal
1118 }
1119 cond := flow_value(cond_signal)
1120 if !e.value_as_bool(cond)! {
1121 mut msg := 'assertion failed'
1122 if node.children_count > 1 {
1123 msg = e.display_string(e.eval_expr(e.child(node, 1))!)!
1124 }
1125 return error('v3.eval: ${msg}')
1126 }
1127 return normal_flow()
1128 }
1129 .defer_stmt {
1130 e.register_defer_stmt(id)
1131 return normal_flow()
1132 }
1133 .asm_stmt, .empty, .label_stmt {
1134 return normal_flow()
1135 }
1136 else {
1137 _ = e.eval_expr(id)!
1138 return normal_flow()
1139 }
1140 }
1141}
1142
1143fn (mut e Eval) register_defer_stmt(id flat.NodeId) {
1144 if e.scopes.len == 0 {
1145 e.open_scope()
1146 }
1147 node := e.node(id)
1148 scope_idx := if node.value == 'function' && e.call_stack.len > 0
1149 && e.call_stack[e.call_stack.len - 1].scope_idx >= 0 {
1150 e.call_stack[e.call_stack.len - 1].scope_idx
1151 } else {
1152 e.scopes.len - 1
1153 }
1154 e.scopes[scope_idx].defer_stmts << id
1155}
1156
1157fn (mut e Eval) run_deferred_stmts() ! {
1158 if e.scopes.len == 0 {
1159 return
1160 }
1161 scope_idx := e.scopes.len - 1
1162 defer_stmts := e.scopes[scope_idx].defer_stmts.clone()
1163 e.scopes[scope_idx].defer_stmts = []flat.NodeId{}
1164 for i := defer_stmts.len; i > 0; i-- {
1165 defer_id := defer_stmts[i - 1]
1166 defer_node := e.node(defer_id)
1167 for child_id in e.children(defer_node) {
1168 signal := e.exec_stmt(child_id)!
1169 if signal.kind != .normal {
1170 return error('v3.eval: unexpected `${signal.kind}` escaped defer')
1171 }
1172 }
1173 }
1174}
1175
1176fn (mut e Eval) exec_assign(node &flat.Node, declare bool) !FlowSignal {
1177 children := e.children(node)
1178 if children.len == 0 {
1179 return normal_flow()
1180 }
1181 if children.len == 2 {
1182 lhs_id := children[0]
1183 rhs_id := children[1]
1184 if node.op != .assign && node.op != .none && e.target_needs_single_eval(lhs_id) {
1185 return e.exec_compound_assignment_pair_flow(node.op, lhs_id, rhs_id, declare)
1186 }
1187 target_type := e.assignment_target_type_name(lhs_id, declare)
1188 signal := e.assignment_value_flow(node.op, lhs_id, rhs_id, target_type)!
1189 if signal.kind != .normal {
1190 return signal
1191 }
1192 assign_signal := e.assign_target_typed_flow(lhs_id, flow_value(signal), declare, if target_type.len > 0 {
1193 target_type
1194 } else {
1195 e.infer_expr_type_name(rhs_id)
1196 })!
1197 if assign_signal.kind != .normal {
1198 return assign_signal
1199 }
1200 return normal_flow()
1201 }
1202 if children.len > 2 {
1203 first_target_type := e.assignment_target_type_name(children[0], declare)
1204 first_signal := e.assignment_value_flow(node.op, children[0], children[1],
1205 first_target_type)!
1206 if first_signal.kind != .normal {
1207 return first_signal
1208 }
1209 value := flow_value(first_signal)
1210 mut lhs_ids := [children[0]]
1211 for i := 2; i < children.len; i++ {
1212 lhs_ids << children[i]
1213 }
1214 if value is TupleValue {
1215 for i, lhs_id in lhs_ids {
1216 item := if i < value.values.len { value.values[i] } else { void_value() }
1217 assign_signal := e.assign_target_flow(lhs_id, item, declare)!
1218 if assign_signal.kind != .normal {
1219 return assign_signal
1220 }
1221 }
1222 return normal_flow()
1223 }
1224 if children.len % 2 == 1 {
1225 for i, lhs_id in lhs_ids {
1226 item := if i == 0 { value } else { void_value() }
1227 assign_signal := e.assign_target_flow(lhs_id, item, declare)!
1228 if assign_signal.kind != .normal {
1229 return assign_signal
1230 }
1231 }
1232 return normal_flow()
1233 }
1234 mut assign_lhs_ids := [children[0]]
1235 mut values := [value]
1236 mut i := 2
1237 for i < children.len {
1238 lhs_id := children[i]
1239 rhs_id := if i + 1 < children.len { children[i + 1] } else { flat.empty_node }
1240 item := if int(rhs_id) >= 0 {
1241 target_type := e.assignment_target_type_name(lhs_id, declare)
1242 signal := e.assignment_value_flow(node.op, lhs_id, rhs_id, target_type)!
1243 if signal.kind != .normal {
1244 return signal
1245 }
1246 flow_value(signal)
1247 } else {
1248 void_value()
1249 }
1250 assign_lhs_ids << lhs_id
1251 values << item
1252 i += 2
1253 }
1254 for idx, lhs_id in assign_lhs_ids {
1255 assign_signal := e.assign_target_flow(lhs_id, values[idx], declare)!
1256 if assign_signal.kind != .normal {
1257 return assign_signal
1258 }
1259 }
1260 return normal_flow()
1261 }
1262 mut i := 0
1263 for i < children.len {
1264 lhs_id := children[i]
1265 rhs_id := if i + 1 < children.len { children[i + 1] } else { flat.empty_node }
1266 value := if int(rhs_id) >= 0 {
1267 target_type := e.assignment_target_type_name(lhs_id, declare)
1268 signal := e.assignment_value_flow(node.op, lhs_id, rhs_id, target_type)!
1269 if signal.kind != .normal {
1270 return signal
1271 }
1272 flow_value(signal)
1273 } else {
1274 void_value()
1275 }
1276 assign_signal := e.assign_target_flow(lhs_id, value, declare)!
1277 if assign_signal.kind != .normal {
1278 return assign_signal
1279 }
1280 i += 2
1281 }
1282 return normal_flow()
1283}
1284
1285fn (e &Eval) target_needs_single_eval(id flat.NodeId) bool {
1286 if int(id) < 0 {
1287 return false
1288 }
1289 return e.node(id).kind in [.index, .selector]
1290}
1291
1292fn (mut e Eval) exec_compound_assignment_pair_flow(op flat.Op, lhs_id flat.NodeId, rhs_id flat.NodeId, declare bool) !FlowSignal {
1293 target_type := e.assignment_target_type_name(lhs_id, declare)
1294 rhs_signal := e.eval_expr_flow_expected(rhs_id, target_type)!
1295 if rhs_signal.kind != .normal {
1296 return rhs_signal
1297 }
1298 rhs := flow_value(rhs_signal)
1299 return e.apply_compound_target_flow(op, lhs_id, rhs, declare, if target_type.len > 0 {
1300 target_type
1301 } else {
1302 e.infer_expr_type_name(rhs_id)
1303 })
1304}
1305
1306fn (mut e Eval) apply_compound_target_flow(op flat.Op, lhs_id flat.NodeId, rhs Value, declare bool, type_name string) !FlowSignal {
1307 node := e.node(lhs_id)
1308 match node.kind {
1309 .index {
1310 return e.update_resolved_lvalue_with_op_flow(lhs_id, op, rhs)
1311 }
1312 .selector {
1313 return e.update_resolved_lvalue_with_op_flow(lhs_id, op, rhs)
1314 }
1315 else {
1316 left_signal := e.eval_expr_flow(lhs_id)!
1317 if left_signal.kind != .normal {
1318 return left_signal
1319 }
1320 value := e.apply_assignment_op(op, flow_value(left_signal), rhs)!
1321 return e.assign_target_typed_flow(lhs_id, value, declare, type_name)
1322 }
1323 }
1324}
1325
1326fn (mut e Eval) assignment_value(op flat.Op, lhs_id flat.NodeId, rhs_id flat.NodeId) !Value {
1327 rhs := e.eval_expr(rhs_id)!
1328 if op == .assign || op == .none {
1329 return rhs
1330 }
1331 left := e.eval_expr(lhs_id) or { e.zero_value_like(rhs) }
1332 return match op {
1333 .plus_assign { e.apply_infix(.plus, left, rhs)! }
1334 .minus_assign { e.apply_infix(.minus, left, rhs)! }
1335 .mul_assign { e.apply_infix(.mul, left, rhs)! }
1336 .div_assign { e.apply_infix(.div, left, rhs)! }
1337 .mod_assign { e.apply_infix(.mod, left, rhs)! }
1338 .amp_assign { e.apply_infix(.amp, left, rhs)! }
1339 .pipe_assign { e.apply_infix(.pipe, left, rhs)! }
1340 .xor_assign { e.apply_infix(.xor, left, rhs)! }
1341 .left_shift_assign { e.apply_infix(.left_shift, left, rhs)! }
1342 .right_shift_assign { e.apply_infix(.right_shift, left, rhs)! }
1343 .right_shift_unsigned_assign { e.apply_infix(.right_shift_unsigned, left, rhs)! }
1344 else { rhs }
1345 }
1346}
1347
1348fn (mut e Eval) assignment_value_flow(op flat.Op, lhs_id flat.NodeId, rhs_id flat.NodeId, expected_type string) !FlowSignal {
1349 rhs_signal := e.eval_expr_flow_expected(rhs_id, expected_type)!
1350 if rhs_signal.kind != .normal {
1351 return rhs_signal
1352 }
1353 rhs := flow_value(rhs_signal)
1354 if op == .assign || op == .none {
1355 return FlowSignal{
1356 values: [rhs]
1357 }
1358 }
1359 left_signal := e.eval_expr_flow(lhs_id)!
1360 if left_signal.kind != .normal {
1361 return left_signal
1362 }
1363 left := flow_value(left_signal)
1364 return FlowSignal{
1365 values: [e.apply_assignment_op(op, left, rhs)!]
1366 }
1367}
1368
1369fn (mut e Eval) apply_assignment_op(op flat.Op, left Value, rhs Value) !Value {
1370 return match op {
1371 .plus_assign { e.apply_infix(.plus, left, rhs)! }
1372 .minus_assign { e.apply_infix(.minus, left, rhs)! }
1373 .mul_assign { e.apply_infix(.mul, left, rhs)! }
1374 .div_assign { e.apply_infix(.div, left, rhs)! }
1375 .mod_assign { e.apply_infix(.mod, left, rhs)! }
1376 .amp_assign { e.apply_infix(.amp, left, rhs)! }
1377 .pipe_assign { e.apply_infix(.pipe, left, rhs)! }
1378 .xor_assign { e.apply_infix(.xor, left, rhs)! }
1379 .left_shift_assign { e.apply_infix(.left_shift, left, rhs)! }
1380 .right_shift_assign { e.apply_infix(.right_shift, left, rhs)! }
1381 .right_shift_unsigned_assign { e.apply_infix(.right_shift_unsigned, left, rhs)! }
1382 else { rhs }
1383 }
1384}
1385
1386fn (mut e Eval) assignment_target_type_name(lhs_id flat.NodeId, declare bool) string {
1387 if int(lhs_id) < 0 {
1388 return ''
1389 }
1390 node := e.node(lhs_id)
1391 match node.kind {
1392 .ident {
1393 if !declare {
1394 if typ := e.lookup_var_type(node.value) {
1395 return typ
1396 }
1397 }
1398 return node.typ
1399 }
1400 .selector {
1401 if node.children_count > 0 {
1402 base_type := e.infer_expr_type_name(e.child(node, 0))
1403 if base_type.len > 0 {
1404 return e.struct_field_type_name_by_type(base_type, node.value)
1405 }
1406 }
1407 }
1408 .index {
1409 if node.children_count > 0 {
1410 container_type := e.infer_expr_type_name(e.child(node, 0))
1411 if container_type.starts_with('[]') {
1412 return container_type[2..]
1413 }
1414 if is_fixed_array_type_name(container_type) {
1415 return fixed_array_elem_type_name(container_type)
1416 }
1417 if container_type.starts_with('map[') {
1418 _, value_type := split_map_type(container_type)
1419 return value_type
1420 }
1421 }
1422 }
1423 else {}
1424 }
1425
1426 return ''
1427}
1428
1429fn flow_value(signal FlowSignal) Value {
1430 if signal.values.len > 0 {
1431 return signal.values[0]
1432 }
1433 return void_value()
1434}
1435
1436fn flow_values_value(values []Value) Value {
1437 if values.len == 0 {
1438 return void_value()
1439 }
1440 if values.len == 1 {
1441 return values[0]
1442 }
1443 return TupleValue{
1444 values: values.clone()
1445 }
1446}
1447
1448fn flow_values_or_void(values []Value) []Value {
1449 if values.len > 0 {
1450 return values.clone()
1451 }
1452 return [void_value()]
1453}
1454
1455fn (mut e Eval) assign_target(id flat.NodeId, value Value, declare bool) ! {
1456 signal := e.assign_target_typed_flow(id, value, declare, '')!
1457 if signal.kind != .normal {
1458 return error('v3.eval: unexpected `${signal.kind}` escaped assignment target')
1459 }
1460}
1461
1462fn (mut e Eval) assign_target_typed(id flat.NodeId, value Value, declare bool, type_name string) ! {
1463 signal := e.assign_target_typed_flow(id, value, declare, type_name)!
1464 if signal.kind != .normal {
1465 return error('v3.eval: unexpected `${signal.kind}` escaped assignment target')
1466 }
1467}
1468
1469fn (mut e Eval) assign_target_flow(id flat.NodeId, value Value, declare bool) !FlowSignal {
1470 return e.assign_target_typed_flow(id, value, declare, '')
1471}
1472
1473fn (mut e Eval) assign_target_typed_flow(id flat.NodeId, value Value, declare bool, type_name string) !FlowSignal {
1474 node := e.node(id)
1475 match node.kind {
1476 .ident {
1477 if declare {
1478 decl_type := if type_name.len > 0 { type_name } else { node.typ }
1479 e.declare_var_typed(node.value, e.adapt_value_to_type_name(value, decl_type),
1480 decl_type)
1481 } else {
1482 target_type := if existing := e.lookup_var_type(node.value) {
1483 existing
1484 } else {
1485 if type_name.len > 0 { type_name } else { node.typ }
1486 }
1487 e.set_var(node.value, e.adapt_value_to_type_name(value, target_type))!
1488 e.set_var_type(node.value, target_type)
1489 }
1490 }
1491 .selector {
1492 return e.update_resolved_lvalue_flow(id, value)
1493 }
1494 .index {
1495 return e.update_resolved_lvalue_flow(id, value)
1496 }
1497 else {
1498 return error('v3.eval: unsupported assignment target `${node.kind}`')
1499 }
1500 }
1501
1502 return normal_flow()
1503}
1504
1505fn (e &Eval) infer_expr_type_name(id flat.NodeId) string {
1506 if int(id) < 0 {
1507 return ''
1508 }
1509 node := e.node(id)
1510 if node.kind in [.struct_init, .cast_expr, .as_expr] {
1511 return e.normalize_type_name(node.value)
1512 }
1513 if node.typ.len > 0 {
1514 return e.normalize_type_name(node.typ)
1515 }
1516 match node.kind {
1517 .int_literal {
1518 return 'int'
1519 }
1520 .float_literal {
1521 return 'f64'
1522 }
1523 .bool_literal {
1524 return 'bool'
1525 }
1526 .char_literal {
1527 return 'char'
1528 }
1529 .string_literal, .string_interp {
1530 return 'string'
1531 }
1532 .ident {
1533 if typ := e.lookup_var_type(node.value) {
1534 return typ
1535 }
1536 }
1537 .selector {
1538 if node.children_count > 0 {
1539 if typ := e.type_value_name_from_expr(e.child(node, 0)) {
1540 return typ
1541 }
1542 base_type := e.infer_expr_type_name(e.child(node, 0))
1543 if base_type.len > 0 {
1544 return e.struct_field_type_name_by_type(base_type, node.value)
1545 }
1546 }
1547 }
1548 .index {
1549 if node.children_count > 0 {
1550 container_type := e.infer_expr_type_name(e.child(node, 0))
1551 if container_type.starts_with('[]') {
1552 return container_type[2..]
1553 }
1554 if is_fixed_array_type_name(container_type) {
1555 return fixed_array_elem_type_name(container_type)
1556 }
1557 if container_type.starts_with('map[') {
1558 _, value_type := split_map_type(container_type)
1559 return value_type
1560 }
1561 }
1562 }
1563 .array_literal {
1564 elem_type_name := e.array_literal_elem_type_name(node)
1565 if elem_type_name.len > 0 {
1566 return '[]${elem_type_name}'
1567 }
1568 }
1569 else {}
1570 }
1571
1572 return ''
1573}
1574
1575fn (e &Eval) array_literal_elem_type_name(node &flat.Node) string {
1576 if node.typ.len > 0 {
1577 return array_elem_type_name_from_type(node.typ)
1578 }
1579 if node.value.len > 0 {
1580 return array_elem_type_name_from_type(node.value)
1581 }
1582 if node.children_count > 0 {
1583 return e.infer_expr_type_name(e.child(node, 0))
1584 }
1585 return ''
1586}
1587
1588fn array_elem_type_name_from_type(type_name string) string {
1589 if type_name.starts_with('[]') {
1590 return type_name[2..]
1591 }
1592 if is_fixed_array_type_name(type_name) {
1593 return fixed_array_elem_type_name(type_name)
1594 }
1595 return ''
1596}
1597
1598fn (mut e Eval) update_target(id flat.NodeId, value Value) ! {
1599 signal := e.update_target_flow(id, value)!
1600 if signal.kind != .normal {
1601 return error('v3.eval: unexpected `${signal.kind}` escaped assignment target')
1602 }
1603}
1604
1605fn (mut e Eval) update_target_flow(id flat.NodeId, value Value) !FlowSignal {
1606 return e.assign_target_flow(id, value, false)
1607}
1608
1609fn (mut e Eval) update_resolved_lvalue_flow(id flat.NodeId, value Value) !FlowSignal {
1610 resolved := e.resolve_lvalue_flow(id)!
1611 if resolved.signal.kind != .normal {
1612 return resolved.signal
1613 }
1614 return e.write_resolved_lvalue_flow(resolved, value)
1615}
1616
1617fn (mut e Eval) update_resolved_lvalue_with_op_flow(id flat.NodeId, op flat.Op, rhs Value) !FlowSignal {
1618 resolved := e.resolve_lvalue_flow(id)!
1619 if resolved.signal.kind != .normal {
1620 return resolved.signal
1621 }
1622 value := e.apply_assignment_op(op, resolved.value, rhs)!
1623 return e.write_resolved_lvalue_flow(resolved, value)
1624}
1625
1626fn (mut e Eval) update_resolved_lvalue_postfix_flow(id flat.NodeId, op flat.Op) !FlowSignal {
1627 resolved := e.resolve_lvalue_flow(id)!
1628 if resolved.signal.kind != .normal {
1629 return resolved.signal
1630 }
1631 value := e.apply_postfix_op(op, resolved.value)!
1632 update_signal := e.write_resolved_lvalue_flow(resolved, value)!
1633 if update_signal.kind != .normal {
1634 return update_signal
1635 }
1636 return value_flow(resolved.value)
1637}
1638
1639fn (mut e Eval) resolve_lvalue_flow(id flat.NodeId) !ResolvedLvalue {
1640 node := e.node(id)
1641 match node.kind {
1642 .selector {
1643 mut base := e.resolve_lvalue_flow(e.child(node, 0))!
1644 if base.signal.kind != .normal {
1645 return base
1646 }
1647 value := e.eval_selector_value(base.value, node.value)!
1648 base.steps << LvalueStep{
1649 kind: .selector
1650 container: base.value
1651 index: void_value()
1652 field_name: node.value
1653 }
1654 base.value = value
1655 return base
1656 }
1657 .index {
1658 mut base := e.resolve_lvalue_flow(e.child(node, 0))!
1659 if base.signal.kind != .normal {
1660 return base
1661 }
1662 index_signal := if base.value is MapValue {
1663 e.eval_expr_flow_expected(e.child(node, 1), base.value.key_type_name)!
1664 } else {
1665 e.eval_expr_flow(e.child(node, 1))!
1666 }
1667 if index_signal.kind != .normal {
1668 return ResolvedLvalue{
1669 signal: index_signal
1670 }
1671 }
1672 index := flow_value(index_signal)
1673 value := e.index_value(base.value, index)!
1674 base.steps << LvalueStep{
1675 kind: .index
1676 container: base.value
1677 index: index
1678 }
1679 base.value = value
1680 return base
1681 }
1682 else {
1683 signal := e.eval_expr_flow(id)!
1684 if signal.kind != .normal {
1685 return ResolvedLvalue{
1686 signal: signal
1687 }
1688 }
1689 return ResolvedLvalue{
1690 root_id: id
1691 value: flow_value(signal)
1692 }
1693 }
1694 }
1695}
1696
1697fn (mut e Eval) write_resolved_lvalue_flow(resolved ResolvedLvalue, value Value) !FlowSignal {
1698 mut new_value := value
1699 for i := resolved.steps.len - 1; i >= 0; i-- {
1700 step := resolved.steps[i]
1701 match step.kind {
1702 .index {
1703 new_value = e.set_index_value(step.container, step.index, new_value)!
1704 }
1705 .selector {
1706 new_value = e.set_selector_value(step.container, step.field_name, new_value)!
1707 }
1708 else {}
1709 }
1710 }
1711 return e.update_target_flow(resolved.root_id, new_value)
1712}
1713
1714fn (mut e Eval) set_index_value(container Value, index Value, value Value) !Value {
1715 match container {
1716 ArrayValue {
1717 mut arr := ArrayValue{
1718 elem_type_name: container.elem_type_name
1719 values: container.values.clone()
1720 }
1721 idx := int(e.value_as_int(index)!)
1722 if idx < 0 || idx >= arr.values.len {
1723 return error('v3.eval: array index out of bounds')
1724 }
1725 arr.values[idx] = e.adapt_value_to_type_name(value, arr.elem_type_name)
1726 return arr
1727 }
1728 MapValue {
1729 return e.map_set_value(container, index, value)
1730 }
1731 else {
1732 return error('v3.eval: indexed assignment expects array or map')
1733 }
1734 }
1735}
1736
1737fn (mut e Eval) set_selector_value(container Value, field_name string, value Value) !Value {
1738 match container {
1739 StructValue {
1740 mut st := container
1741 st.fields[field_name] = e.adapt_value_to_type_name(value, e.struct_field_type_name(container,
1742 field_name))
1743 return st
1744 }
1745 SumValue {
1746 mut sv := container
1747 sv.payload = e.set_selector_value(sv.payload, field_name, value)!
1748 return sv
1749 }
1750 else {
1751 return error('v3.eval: selector assignment expects struct, got `${e.runtime_type_name(container)}`')
1752 }
1753 }
1754}
1755
1756fn (mut e Eval) exec_array_append(node &flat.Node) !FlowSignal {
1757 lhs_id := e.child(node, 0)
1758 rhs_id := e.child(node, 1)
1759 resolved := e.resolve_lvalue_flow(lhs_id)!
1760 if resolved.signal.kind != .normal {
1761 return resolved.signal
1762 }
1763 current := resolved.value
1764 if current !is ArrayValue {
1765 return error('v3.eval: `<<` is only supported for arrays')
1766 }
1767 mut arr := current as ArrayValue
1768 rhs_type_name := e.infer_expr_type_name(rhs_id)
1769 rhs_expected_type := if rhs_type_name.len > 0
1770 && e.array_type_spreads_into_elem(rhs_type_name, arr.elem_type_name) {
1771 rhs_type_name
1772 } else {
1773 arr.elem_type_name
1774 }
1775 rhs_signal := e.eval_expr_flow_expected(rhs_id, rhs_expected_type)!
1776 if rhs_signal.kind != .normal {
1777 return rhs_signal
1778 }
1779 rhs := flow_value(rhs_signal)
1780 if rhs is ArrayValue && e.array_append_rhs_spreads(rhs_id, rhs, arr.elem_type_name) {
1781 for item in rhs.values {
1782 arr.values << e.adapt_value_to_type_name(item, arr.elem_type_name)
1783 }
1784 } else {
1785 arr.values << e.adapt_value_to_type_name(rhs, arr.elem_type_name)
1786 }
1787 return e.write_resolved_lvalue_flow(resolved, arr)
1788}
1789
1790fn (e &Eval) array_append_rhs_spreads(rhs_id flat.NodeId, rhs ArrayValue, elem_type_name string) bool {
1791 rhs_type_name := e.infer_expr_type_name(rhs_id)
1792 if rhs_type_name.len > 0 {
1793 return e.array_type_spreads_into_elem(rhs_type_name, elem_type_name)
1794 }
1795 if rhs.elem_type_name.len > 0 {
1796 return e.type_name_matches(rhs.elem_type_name, elem_type_name)
1797 }
1798 return false
1799}
1800
1801fn (e &Eval) array_type_spreads_into_elem(array_type_name string, elem_type_name string) bool {
1802 rhs_elem_type_name := array_elem_type_name_from_type(array_type_name)
1803 if rhs_elem_type_name.len == 0 {
1804 return false
1805 }
1806 return e.type_name_matches(rhs_elem_type_name, elem_type_name)
1807}
1808
1809fn (mut e Eval) exec_if(node &flat.Node) !FlowSignal {
1810 if node.children_count < 2 {
1811 return normal_flow()
1812 }
1813 cond_id := e.child(node, 0)
1814 cond_is_guard := e.node(cond_id).kind == .decl_assign
1815 if cond_is_guard {
1816 e.open_scope()
1817 }
1818 cond_signal := e.eval_condition_flow(cond_id)!
1819 if cond_signal.kind != .normal {
1820 if cond_is_guard {
1821 e.close_scope()!
1822 }
1823 return cond_signal
1824 }
1825 if e.value_as_bool(flow_value(cond_signal))! {
1826 mut smartcast_scope := false
1827 if !cond_is_guard {
1828 if binding := e.smartcast_binding_from_condition(cond_id) {
1829 e.open_scope()
1830 e.declare_var_typed(binding.name, binding.value, binding.type_name)
1831 smartcast_scope = true
1832 }
1833 }
1834 signal := e.exec_stmt(e.child(node, 1))!
1835 if smartcast_scope {
1836 e.close_scope()!
1837 }
1838 if cond_is_guard {
1839 e.close_scope()!
1840 }
1841 return signal
1842 }
1843 if cond_is_guard {
1844 e.close_scope()!
1845 }
1846 if node.children_count > 2 {
1847 return e.exec_stmt(e.child(node, 2))
1848 }
1849 return normal_flow()
1850}
1851
1852fn (mut e Eval) smartcast_binding_from_condition(cond_id flat.NodeId) ?SmartcastBinding {
1853 if int(cond_id) < 0 {
1854 return none
1855 }
1856 node := e.node(cond_id)
1857 if node.kind == .paren {
1858 return e.smartcast_binding_from_condition(e.child(node, 0))
1859 }
1860 if node.kind == .infix && node.op == .logical_and {
1861 return e.smartcast_binding_from_condition(e.child(node, 0))
1862 }
1863 if node.kind != .is_expr || node.children_count == 0 {
1864 return none
1865 }
1866 left_id := e.child(node, 0)
1867 left := e.node(left_id)
1868 if left.kind != .ident {
1869 return none
1870 }
1871 found := e.lookup_var(left.value)
1872 if !found.found {
1873 return none
1874 }
1875 if value := e.smartcast_value(found.value, node.value) {
1876 return SmartcastBinding{
1877 name: left.value
1878 value: value
1879 type_name: e.normalize_type_name(node.value)
1880 }
1881 }
1882 return none
1883}
1884
1885fn (e &Eval) smartcast_value(value Value, target_type string) ?Value {
1886 if value is SumValue {
1887 if e.type_name_matches(value.variant_name, target_type)
1888 || e.value_matches_type_name(value.payload, target_type) {
1889 return value.payload
1890 }
1891 }
1892 return none
1893}
1894
1895fn (mut e Eval) eval_condition(id flat.NodeId) !bool {
1896 signal := e.eval_condition_flow(id)!
1897 return e.value_as_bool(flow_value(signal))
1898}
1899
1900fn (mut e Eval) eval_condition_flow(id flat.NodeId) !FlowSignal {
1901 node := e.node(id)
1902 if node.kind == .decl_assign {
1903 rhs_id := e.child(node, 1)
1904 rhs_node := e.node(rhs_id)
1905 mut ok := false
1906 mut bind_value := Value(void_value())
1907 mut bind_type := ''
1908 if rhs_node.kind == .index && rhs_node.value != 'range' && rhs_node.children_count > 1 {
1909 container_signal := e.eval_expr_flow(e.child(rhs_node, 0))!
1910 if container_signal.kind != .normal {
1911 return container_signal
1912 }
1913 container := flow_value(container_signal)
1914 index_signal := if container is MapValue {
1915 e.eval_expr_flow_expected(e.child(rhs_node, 1), container.key_type_name)!
1916 } else {
1917 e.eval_expr_flow(e.child(rhs_node, 1))!
1918 }
1919 if index_signal.kind != .normal {
1920 return index_signal
1921 }
1922 if container is MapValue {
1923 value, found := e.map_lookup(container, flow_value(index_signal))
1924 ok = found
1925 bind_value = value
1926 bind_type = container.value_type_name
1927 } else {
1928 value := e.index_value(container, flow_value(index_signal))!
1929 ok = e.value_is_truthy(value)
1930 bind_value = e.unwrap_option_like(value)
1931 bind_type = e.guard_binding_type_name(rhs_id, value)
1932 }
1933 } else {
1934 rhs_signal := e.eval_expr_flow(rhs_id)!
1935 if rhs_signal.kind != .normal {
1936 return rhs_signal
1937 }
1938 value := flow_value(rhs_signal)
1939 ok = e.value_is_truthy(value)
1940 bind_value = e.unwrap_option_like(value)
1941 bind_type = e.guard_binding_type_name(rhs_id, value)
1942 }
1943 if ok {
1944 e.assign_target_typed(e.child(node, 0), bind_value, true, bind_type)!
1945 }
1946 return value_flow(Value(ok))
1947 }
1948 signal := e.eval_expr_flow(id)!
1949 if signal.kind != .normal {
1950 return signal
1951 }
1952 return value_flow(Value(e.value_as_bool(flow_value(signal))!))
1953}
1954
1955fn (e &Eval) guard_binding_type_name(rhs_id flat.NodeId, value Value) string {
1956 rhs_type := e.infer_expr_type_name(rhs_id)
1957 name := rhs_type.trim_left('&')
1958 if name.starts_with('?') || name.starts_with('!') {
1959 return name[1..]
1960 }
1961 if name.len > 0 {
1962 return name
1963 }
1964 return e.runtime_type_name(e.unwrap_option_like(value))
1965}
1966
1967fn (e &Eval) unwrap_option_like(value Value) Value {
1968 if value is StructValue {
1969 if 'data' in value.fields {
1970 return value.fields['data'] or { void_value() }
1971 }
1972 }
1973 return value
1974}
1975
1976fn (e &Eval) value_is_truthy(value Value) bool {
1977 match value {
1978 bool {
1979 return value
1980 }
1981 VoidValue {
1982 return false
1983 }
1984 StructValue {
1985 state := value.fields['state'] or { void_value() }
1986 if state is i64 {
1987 return state == 0
1988 }
1989 is_error := value.fields['is_error'] or { void_value() }
1990 if is_error is bool {
1991 return !is_error
1992 }
1993 return true
1994 }
1995 else {
1996 return true
1997 }
1998 }
1999}
2000
2001fn (mut e Eval) exec_for(node &flat.Node, loop_label string) !FlowSignal {
2002 if node.children_count < 3 {
2003 return normal_flow()
2004 }
2005 init_id := e.child(node, 0)
2006 cond_id := e.child(node, 1)
2007 post_id := e.child(node, 2)
2008 e.open_scope()
2009 if int(init_id) >= 0 && e.node(init_id).kind != .empty {
2010 init_signal := e.exec_stmt(init_id)!
2011 if init_signal.kind != .normal {
2012 e.close_scope()!
2013 return init_signal
2014 }
2015 }
2016 body := e.children(node)
2017 for {
2018 if int(cond_id) >= 0 && e.node(cond_id).kind != .empty {
2019 cond_signal := e.eval_condition_flow(cond_id)!
2020 if cond_signal.kind != .normal {
2021 e.close_scope()!
2022 return cond_signal
2023 }
2024 if !e.value_as_bool(flow_value(cond_signal))! {
2025 break
2026 }
2027 }
2028 e.open_scope()
2029 signal := e.exec_stmts(body[3..])!
2030 e.close_scope()!
2031 if signal.kind == .break_ {
2032 if e.flow_targets_loop(signal, loop_label) {
2033 e.close_scope()!
2034 return normal_flow()
2035 }
2036 e.close_scope()!
2037 return signal
2038 }
2039 if signal.kind == .continue_ {
2040 if !e.flow_targets_loop(signal, loop_label) {
2041 e.close_scope()!
2042 return signal
2043 }
2044 }
2045 if signal.kind == .return_ {
2046 e.close_scope()!
2047 return signal
2048 }
2049 if int(post_id) >= 0 && e.node(post_id).kind != .empty {
2050 post_signal := e.exec_stmt(post_id)!
2051 if post_signal.kind != .normal {
2052 e.close_scope()!
2053 return post_signal
2054 }
2055 }
2056 }
2057 e.close_scope()!
2058 return normal_flow()
2059}
2060
2061fn (mut e Eval) exec_for_in(node &flat.Node, loop_label string) !FlowSignal {
2062 header_count := if node.value.int() > 0 { node.value.int() } else { 3 }
2063 key_id := e.child(node, 0)
2064 val_id := e.child(node, 1)
2065 container_id := e.child(node, 2)
2066 is_mut_loop := node.op == .amp
2067 mut resolved_container := ResolvedLvalue{}
2068 mut has_resolved_container := false
2069 mut container := Value(void_value())
2070 if is_mut_loop && e.is_assignable_target(container_id) {
2071 resolved_container = e.resolve_lvalue_flow(container_id)!
2072 if resolved_container.signal.kind != .normal {
2073 return resolved_container.signal
2074 }
2075 container = resolved_container.value
2076 has_resolved_container = true
2077 } else {
2078 container_signal := e.eval_expr_flow(container_id)!
2079 if container_signal.kind != .normal {
2080 return container_signal
2081 }
2082 container = flow_value(container_signal)
2083 }
2084 body := e.children(node)[header_count..]
2085 if header_count == 4 {
2086 start := e.value_as_int(container)!
2087 end_signal := e.eval_expr_flow(e.child(node, 3))!
2088 if end_signal.kind != .normal {
2089 return end_signal
2090 }
2091 end := e.value_as_int(flow_value(end_signal))!
2092 for i := start; i < end; i++ {
2093 e.open_scope()
2094 e.assign_loop_vars(key_id, val_id, Value(i), void_value(), false)
2095 signal := e.exec_stmts(body)!
2096 e.close_scope()!
2097 if signal.kind == .break_ {
2098 if e.flow_targets_loop(signal, loop_label) {
2099 return normal_flow()
2100 }
2101 return signal
2102 }
2103 if signal.kind == .continue_ {
2104 if e.flow_targets_loop(signal, loop_label) {
2105 continue
2106 }
2107 return signal
2108 }
2109 if signal.kind == .return_ {
2110 return signal
2111 }
2112 }
2113 return normal_flow()
2114 }
2115 match container {
2116 RangeValue {
2117 last := if container.inclusive { container.end + 1 } else { container.end }
2118 for i := container.start; i < last; i++ {
2119 e.open_scope()
2120 e.assign_loop_vars(key_id, val_id, Value(i), void_value(), false)
2121 signal := e.exec_stmts(body)!
2122 e.close_scope()!
2123 if signal.kind == .break_ {
2124 if e.flow_targets_loop(signal, loop_label) {
2125 return normal_flow()
2126 }
2127 return signal
2128 }
2129 if signal.kind == .continue_ {
2130 if e.flow_targets_loop(signal, loop_label) {
2131 continue
2132 }
2133 return signal
2134 }
2135 if signal.kind == .return_ {
2136 return signal
2137 }
2138 }
2139 }
2140 ArrayValue {
2141 mut arr := ArrayValue{
2142 elem_type_name: container.elem_type_name
2143 values: container.values.clone()
2144 }
2145 for i, item in arr.values {
2146 e.open_scope()
2147 e.assign_loop_vars(key_id, val_id, Value(i64(i)), item, true)
2148 signal := e.exec_stmts(body)!
2149 if is_mut_loop {
2150 if value := e.loop_mut_value(key_id, val_id, true) {
2151 arr.values[i] = e.adapt_value_to_type_name(value, arr.elem_type_name)
2152 mut write_signal := FlowSignal{}
2153 if has_resolved_container {
2154 write_signal = e.write_resolved_lvalue_flow(resolved_container, arr) or {
2155 e.close_scope()!
2156 return err
2157 }
2158 } else {
2159 write_signal = e.update_target_flow(container_id, arr) or {
2160 e.close_scope()!
2161 return err
2162 }
2163 }
2164 if write_signal.kind != .normal {
2165 e.close_scope()!
2166 return write_signal
2167 }
2168 }
2169 }
2170 e.close_scope()!
2171 if signal.kind == .break_ {
2172 if e.flow_targets_loop(signal, loop_label) {
2173 return normal_flow()
2174 }
2175 return signal
2176 }
2177 if signal.kind == .continue_ {
2178 if e.flow_targets_loop(signal, loop_label) {
2179 continue
2180 }
2181 return signal
2182 }
2183 if signal.kind == .return_ {
2184 return signal
2185 }
2186 }
2187 }
2188 MapValue {
2189 mut m := MapValue{
2190 key_type_name: container.key_type_name
2191 value_type_name: container.value_type_name
2192 default_value: container.default_value
2193 entries: container.entries.clone()
2194 }
2195 for i, entry in m.entries {
2196 e.open_scope()
2197 e.assign_loop_vars(key_id, val_id, entry.key, entry.value, true)
2198 signal := e.exec_stmts(body)!
2199 if is_mut_loop {
2200 if value := e.loop_mut_value(key_id, val_id, true) {
2201 m.entries[i].value = e.adapt_value_to_type_name(value, m.value_type_name)
2202 mut write_signal := FlowSignal{}
2203 if has_resolved_container {
2204 write_signal = e.write_resolved_lvalue_flow(resolved_container, m) or {
2205 e.close_scope()!
2206 return err
2207 }
2208 } else {
2209 write_signal = e.update_target_flow(container_id, m) or {
2210 e.close_scope()!
2211 return err
2212 }
2213 }
2214 if write_signal.kind != .normal {
2215 e.close_scope()!
2216 return write_signal
2217 }
2218 }
2219 }
2220 e.close_scope()!
2221 if signal.kind == .break_ {
2222 if e.flow_targets_loop(signal, loop_label) {
2223 return normal_flow()
2224 }
2225 return signal
2226 }
2227 if signal.kind == .continue_ {
2228 if e.flow_targets_loop(signal, loop_label) {
2229 continue
2230 }
2231 return signal
2232 }
2233 if signal.kind == .return_ {
2234 return signal
2235 }
2236 }
2237 }
2238 string {
2239 for i, ch in container {
2240 e.open_scope()
2241 e.assign_loop_vars(key_id, val_id, Value(i64(i)), Value(i64(ch)), true)
2242 signal := e.exec_stmts(body)!
2243 e.close_scope()!
2244 if signal.kind == .break_ {
2245 if e.flow_targets_loop(signal, loop_label) {
2246 return normal_flow()
2247 }
2248 return signal
2249 }
2250 if signal.kind == .continue_ {
2251 if e.flow_targets_loop(signal, loop_label) {
2252 continue
2253 }
2254 return signal
2255 }
2256 if signal.kind == .return_ {
2257 return signal
2258 }
2259 }
2260 }
2261 else {
2262 return error('v3.eval: unsupported for-in iterable `${e.runtime_type_name(container)}`')
2263 }
2264 }
2265
2266 return normal_flow()
2267}
2268
2269fn (e &Eval) flow_targets_loop(signal FlowSignal, loop_label string) bool {
2270 return signal.label.len == 0 || signal.label == loop_label
2271}
2272
2273fn (mut e Eval) assign_loop_vars(key_id flat.NodeId, val_id flat.NodeId, key Value, value Value, has_value bool) {
2274 if int(val_id) >= 0 && e.node(val_id).kind != .empty {
2275 e.assign_target(key_id, key, true) or {}
2276 e.assign_target(val_id, value, true) or {}
2277 } else if has_value {
2278 e.assign_target(key_id, value, true) or {}
2279 } else {
2280 e.assign_target(key_id, key, true) or {}
2281 }
2282}
2283
2284fn (e &Eval) loop_mut_value(key_id flat.NodeId, val_id flat.NodeId, has_value bool) ?Value {
2285 mut value_id := key_id
2286 if int(val_id) >= 0 && e.node(val_id).kind != .empty {
2287 value_id = val_id
2288 } else if !has_value {
2289 return none
2290 }
2291 value_node := e.node(value_id)
2292 if value_node.kind != .ident {
2293 return none
2294 }
2295 found := e.lookup_var(value_node.value)
2296 if !found.found {
2297 return none
2298 }
2299 return found.value
2300}
2301
2302fn (mut e Eval) eval_expr(id flat.NodeId) !Value {
2303 if int(id) < 0 {
2304 return void_value()
2305 }
2306 node := e.node(id)
2307 match node.kind {
2308 .empty {
2309 return void_value()
2310 }
2311 .int_literal {
2312 return Value(strconv.parse_int(clean_number_literal(node.value), 0, 64) or { i64(0) })
2313 }
2314 .float_literal {
2315 return Value(strconv.atof64(clean_number_literal(node.value)) or { 0.0 })
2316 }
2317 .bool_literal {
2318 return Value(node.value == 'true')
2319 }
2320 .char_literal {
2321 return Value(e.char_literal_value(node.value))
2322 }
2323 .string_literal {
2324 return Value(node.value)
2325 }
2326 .string_interp {
2327 return flow_value(e.eval_string_interp_flow(node)!)
2328 }
2329 .ident {
2330 return e.eval_ident(node.value)
2331 }
2332 .enum_val {
2333 return e.lookup_const(e.current_module_name(), node.value) or { Value(i64(0)) }
2334 }
2335 .paren {
2336 return e.eval_expr(e.child(node, 0))
2337 }
2338 .prefix {
2339 return e.eval_prefix(node)
2340 }
2341 .postfix {
2342 return e.eval_postfix(node)
2343 }
2344 .infix {
2345 if node.op == .logical_and {
2346 left := e.eval_expr(e.child(node, 0))!
2347 if !e.value_as_bool(left)! {
2348 return Value(false)
2349 }
2350 return Value(e.value_as_bool(e.eval_expr(e.child(node, 1))!)!)
2351 }
2352 if node.op == .logical_or {
2353 left := e.eval_expr(e.child(node, 0))!
2354 if e.value_as_bool(left)! {
2355 return Value(true)
2356 }
2357 return Value(e.value_as_bool(e.eval_expr(e.child(node, 1))!)!)
2358 }
2359 return e.apply_infix(node.op, e.eval_expr(e.child(node, 0))!, e.eval_expr(e.child(node,
2360 1))!)
2361 }
2362 .call {
2363 return flow_value(e.eval_call_flow(id, node)!)
2364 }
2365 .selector {
2366 return e.eval_selector(node)
2367 }
2368 .index {
2369 return e.eval_index(node)
2370 }
2371 .if_expr {
2372 return e.eval_if_value(node)
2373 }
2374 .block {
2375 return e.eval_block_value(node)
2376 }
2377 .array_literal {
2378 mut values := []Value{}
2379 elem_type_name := e.array_literal_elem_type_name(node)
2380 for child_id in e.children(node) {
2381 values << e.adapt_value_to_type_name(e.eval_expr_expected(child_id, elem_type_name)!,
2382 elem_type_name)
2383 }
2384 return ArrayValue{
2385 elem_type_name: elem_type_name
2386 values: values
2387 }
2388 }
2389 .array_init {
2390 return e.eval_array_init(node)
2391 }
2392 .map_init {
2393 return flow_value(e.eval_map_init_flow(node)!)
2394 }
2395 .struct_init {
2396 return e.eval_struct_init(node)
2397 }
2398 .assoc {
2399 return e.eval_assoc(node)
2400 }
2401 .range {
2402 return RangeValue{
2403 start: e.value_as_int(e.eval_expr(e.child(node, 0))!)!
2404 end: e.value_as_int(e.eval_expr(e.child(node, 1))!)!
2405 }
2406 }
2407 .cast_expr, .as_expr {
2408 value := e.eval_expr(e.child(node, 0))!
2409 return e.cast_value(value, node.value)
2410 }
2411 .is_expr {
2412 value := e.eval_expr(e.child(node, 0))!
2413 return Value(e.value_matches_type_name(value, node.value))
2414 }
2415 .in_expr {
2416 left := e.eval_expr(e.child(node, 0))!
2417 right := e.eval_expr(e.child(node, 1))!
2418 return Value(e.value_in(left, right))
2419 }
2420 .or_expr {
2421 return e.eval_or_expr(node)
2422 }
2423 .match_stmt {
2424 return e.eval_match_value(node)
2425 }
2426 .none_expr, .nil_literal {
2427 return void_value()
2428 }
2429 .sizeof_expr {
2430 return Value(e.sizeof_type_name(node.value))
2431 }
2432 .typeof_expr {
2433 value := e.eval_expr(e.child(node, 0))!
2434 return TypeValue{
2435 name: e.runtime_type_name(value)
2436 }
2437 }
2438 .fn_literal {
2439 return Value(e.eval_fn_literal(id, node)!)
2440 }
2441 else {
2442 return error('v3.eval: unsupported expression `${node.kind}`')
2443 }
2444 }
2445}
2446
2447fn (mut e Eval) eval_fn_literal(id flat.NodeId, node &flat.Node) !FnValue {
2448 mut captures := map[string]Value{}
2449 mut capture_types := map[string]string{}
2450 for child_id in e.children(node) {
2451 child := e.node(child_id)
2452 if child.kind != .ident {
2453 break
2454 }
2455 found := e.lookup_var(child.value)
2456 if !found.found {
2457 return error('v3.eval: unknown captured variable `${child.value}`')
2458 }
2459 captures[child.value] = found.value
2460 if typ := e.lookup_var_type(child.value) {
2461 capture_types[child.value] = typ
2462 }
2463 }
2464 return FnValue{
2465 node: id
2466 module_name: e.current_module_name()
2467 file_name: e.current_file_name()
2468 captures: captures
2469 capture_types: capture_types
2470 }
2471}
2472
2473fn (mut e Eval) eval_expr_flow(id flat.NodeId) !FlowSignal {
2474 if int(id) < 0 {
2475 return FlowSignal{
2476 values: [void_value()]
2477 }
2478 }
2479 node := e.node(id)
2480 match node.kind {
2481 .or_expr {
2482 return e.eval_or_expr_flow(node)
2483 }
2484 .call {
2485 return e.eval_call_flow(id, node)
2486 }
2487 .index {
2488 return e.eval_index_flow(node)
2489 }
2490 .if_expr {
2491 return e.eval_if_value_flow(node)
2492 }
2493 .match_stmt {
2494 return e.eval_match_value_flow(node)
2495 }
2496 .selector {
2497 left_signal := e.eval_expr_flow(e.child(node, 0))!
2498 if left_signal.kind != .normal {
2499 return left_signal
2500 }
2501 return value_flow(e.eval_selector_value(flow_value(left_signal), node.value)!)
2502 }
2503 .paren {
2504 return e.eval_expr_flow(e.child(node, 0))
2505 }
2506 .prefix {
2507 value_signal := e.eval_expr_flow(e.child(node, 0))!
2508 if value_signal.kind != .normal {
2509 return value_signal
2510 }
2511 return value_flow(e.apply_prefix(node.op, flow_value(value_signal))!)
2512 }
2513 .postfix {
2514 return e.eval_postfix_flow(node)
2515 }
2516 .infix {
2517 return e.eval_infix_flow(node)
2518 }
2519 .range {
2520 start_signal := e.eval_expr_flow(e.child(node, 0))!
2521 if start_signal.kind != .normal {
2522 return start_signal
2523 }
2524 end_signal := e.eval_expr_flow(e.child(node, 1))!
2525 if end_signal.kind != .normal {
2526 return end_signal
2527 }
2528 return value_flow(RangeValue{
2529 start: e.value_as_int(flow_value(start_signal))!
2530 end: e.value_as_int(flow_value(end_signal))!
2531 })
2532 }
2533 .cast_expr, .as_expr {
2534 value_signal := e.eval_expr_flow(e.child(node, 0))!
2535 if value_signal.kind != .normal {
2536 return value_signal
2537 }
2538 return value_flow(e.cast_value(flow_value(value_signal), node.value)!)
2539 }
2540 .is_expr {
2541 value_signal := e.eval_expr_flow(e.child(node, 0))!
2542 if value_signal.kind != .normal {
2543 return value_signal
2544 }
2545 return value_flow(Value(e.value_matches_type_name(flow_value(value_signal), node.value)))
2546 }
2547 .in_expr {
2548 left_signal := e.eval_expr_flow(e.child(node, 0))!
2549 if left_signal.kind != .normal {
2550 return left_signal
2551 }
2552 right_signal := e.eval_expr_flow(e.child(node, 1))!
2553 if right_signal.kind != .normal {
2554 return right_signal
2555 }
2556 return value_flow(Value(e.value_in(flow_value(left_signal), flow_value(right_signal))))
2557 }
2558 .array_literal {
2559 mut values := []Value{}
2560 elem_type_name := e.array_literal_elem_type_name(node)
2561 for child_id in e.children(node) {
2562 child_signal := e.eval_expr_flow_expected(child_id, elem_type_name)!
2563 if child_signal.kind != .normal {
2564 return child_signal
2565 }
2566 values << e.adapt_value_to_type_name(flow_value(child_signal), elem_type_name)
2567 }
2568 return value_flow(ArrayValue{
2569 elem_type_name: elem_type_name
2570 values: values
2571 })
2572 }
2573 .array_init {
2574 return e.eval_array_init_flow(node)
2575 }
2576 .struct_init {
2577 return e.eval_struct_init_flow(node)
2578 }
2579 .map_init {
2580 return e.eval_map_init_flow(node)
2581 }
2582 .assoc {
2583 return e.eval_assoc_flow(node)
2584 }
2585 .string_interp {
2586 return e.eval_string_interp_flow(node)
2587 }
2588 else {
2589 return FlowSignal{
2590 values: [e.eval_expr(id)!]
2591 }
2592 }
2593 }
2594}
2595
2596fn (mut e Eval) eval_expr_expected(id flat.NodeId, expected_type string) !Value {
2597 signal := e.eval_expr_flow_expected(id, expected_type)!
2598 if signal.kind != .normal {
2599 return flow_value(signal)
2600 }
2601 return flow_value(signal)
2602}
2603
2604fn (mut e Eval) eval_expr_flow_expected(id flat.NodeId, expected_type string) !FlowSignal {
2605 if int(id) >= 0 {
2606 node := e.node(id)
2607 if node.kind == .enum_val && expected_type.len > 0 {
2608 if value := e.lookup_enum_value(expected_type, node.value) {
2609 return value_flow(value)
2610 }
2611 }
2612 if expected_type.len > 0 {
2613 match node.kind {
2614 .if_expr {
2615 return e.eval_if_value_flow_expected(node, expected_type)
2616 }
2617 .match_stmt {
2618 return e.eval_match_value_flow_expected(node, expected_type)
2619 }
2620 .block {
2621 return e.eval_block_value_flow_expected(node, expected_type)
2622 }
2623 .paren {
2624 return e.eval_expr_flow_expected(e.child(node, 0), expected_type)
2625 }
2626 else {}
2627 }
2628 }
2629 }
2630 return e.eval_expr_flow(id)
2631}
2632
2633fn (e &Eval) current_return_type() string {
2634 if e.call_stack.len == 0 {
2635 return ''
2636 }
2637 return e.call_stack[e.call_stack.len - 1].return_type
2638}
2639
2640fn return_child_expected_type(return_type string, return_types []string, child_index int, child_count int) string {
2641 if return_types.len > 0 {
2642 if child_count == return_types.len && child_index < return_types.len {
2643 return return_types[child_index]
2644 }
2645 return ''
2646 }
2647 if child_count == 1 {
2648 return return_type
2649 }
2650 return ''
2651}
2652
2653fn (mut e Eval) eval_infix_flow(node &flat.Node) !FlowSignal {
2654 left_signal := e.eval_expr_flow(e.child(node, 0))!
2655 if left_signal.kind != .normal {
2656 return left_signal
2657 }
2658 left := flow_value(left_signal)
2659 if node.op == .logical_and {
2660 if !e.value_as_bool(left)! {
2661 return value_flow(Value(false))
2662 }
2663 mut smartcast_scope := false
2664 if binding := e.smartcast_binding_from_condition(e.child(node, 0)) {
2665 e.open_scope()
2666 e.declare_var_typed(binding.name, binding.value, binding.type_name)
2667 smartcast_scope = true
2668 }
2669 right_signal := e.eval_expr_flow(e.child(node, 1))!
2670 if smartcast_scope {
2671 e.close_scope()!
2672 }
2673 if right_signal.kind != .normal {
2674 return right_signal
2675 }
2676 return value_flow(Value(e.value_as_bool(flow_value(right_signal))!))
2677 }
2678 if node.op == .logical_or {
2679 if e.value_as_bool(left)! {
2680 return value_flow(Value(true))
2681 }
2682 right_signal := e.eval_expr_flow(e.child(node, 1))!
2683 if right_signal.kind != .normal {
2684 return right_signal
2685 }
2686 return value_flow(Value(e.value_as_bool(flow_value(right_signal))!))
2687 }
2688 right_signal := e.eval_expr_flow(e.child(node, 1))!
2689 if right_signal.kind != .normal {
2690 return right_signal
2691 }
2692 return value_flow(e.apply_infix(node.op, left, flow_value(right_signal))!)
2693}
2694
2695fn clean_number_literal(value string) string {
2696 return value.replace('_', '')
2697}
2698
2699fn (e &Eval) char_literal_value(raw string) i64 {
2700 mut s := raw
2701 if s.len >= 2 && ((s[0] == `'` && s[s.len - 1] == `'`)
2702 || (s[0] == `\`` && s[s.len - 1] == `\``)) {
2703 s = s[1..s.len - 1]
2704 }
2705 if s.len == 0 {
2706 return 0
2707 }
2708 if s.len >= 2 && s[0] == `\\` {
2709 return match s[1] {
2710 `n` { i64(`\n`) }
2711 `t` { i64(`\t`) }
2712 `r` { i64(`\r`) }
2713 `\\` { i64(`\\`) }
2714 `'` { i64(`'`) }
2715 `"` { i64(`"`) }
2716 `$` { i64(`$`) }
2717 `0` { i64(0) }
2718 `a` { i64(7) }
2719 `b` { i64(8) }
2720 `f` { i64(12) }
2721 `v` { i64(11) }
2722 else { i64(s[0]) }
2723 }
2724 }
2725 return i64(s[0])
2726}
2727
2728fn (mut e Eval) eval_ident(name string) !Value {
2729 if name == '_' {
2730 return void_value()
2731 }
2732 found := e.lookup_var(name)
2733 if found.found {
2734 return found.value
2735 }
2736 if value := e.lookup_const(e.current_module_name(), name) {
2737 return value
2738 }
2739 mod_name := e.resolve_module_name(name)
2740 if mod_name in e.modules || name in ['os', 'time', 'strings'] {
2741 return ModuleValue{
2742 name: mod_name
2743 }
2744 }
2745 if e.has_type_name(e.current_module_name(), name) {
2746 return TypeValue{
2747 name: e.qualify_type_name(e.current_module_name(), name)
2748 }
2749 }
2750 return e.unknown_variable_error(name)
2751}
2752
2753fn (e &Eval) resolve_module_name(name string) string {
2754 file_name := e.current_file_name()
2755 if file_name in e.file_import_alias {
2756 aliases := e.file_import_alias[file_name].clone()
2757 if name in aliases {
2758 return aliases[name]
2759 }
2760 }
2761 return name
2762}
2763
2764fn (e &Eval) has_type_name(module_name string, name string) bool {
2765 if module_name in e.type_names && name in e.type_names[module_name] {
2766 return true
2767 }
2768 if name.contains('.') {
2769 mod := name.all_before_last('.')
2770 short := name.all_after_last('.')
2771 return mod in e.type_names && short in e.type_names[mod]
2772 }
2773 return name in e.structs || name in e.sum_types
2774}
2775
2776fn (mut e Eval) lookup_const(module_name string, name string) ?Value {
2777 if module_name in e.consts && name in e.consts[module_name] {
2778 mut entry := e.consts[module_name][name]
2779 if entry.cached {
2780 return entry.value
2781 }
2782 if entry.evaluating {
2783 return none
2784 }
2785 entry.evaluating = true
2786 e.consts[module_name][name] = entry
2787 mut value := Value(void_value())
2788 if e.node(entry.node).children_count > 0 {
2789 e.call_stack << CallFrame{
2790 module_name: entry.module_name
2791 file_name: entry.file_name
2792 fn_name: '<const ${name}>'
2793 }
2794 value = e.eval_expr(e.child(e.node(entry.node), 0)) or {
2795 e.call_stack.delete(e.call_stack.len - 1)
2796 entry.evaluating = false
2797 e.consts[module_name][name] = entry
2798 return none
2799 }
2800 e.call_stack.delete(e.call_stack.len - 1)
2801 }
2802 entry.cached = true
2803 entry.evaluating = false
2804 entry.value = value
2805 e.consts[module_name][name] = entry
2806 return value
2807 }
2808 for mod_name in e.consts.keys() {
2809 if name in e.consts[mod_name] {
2810 return e.lookup_const(mod_name, name)
2811 }
2812 }
2813 return none
2814}
2815
2816fn (mut e Eval) eval_call_flow(id flat.NodeId, node &flat.Node) !FlowSignal {
2817 if node.children_count == 0 {
2818 return FlowSignal{
2819 values: [void_value()]
2820 }
2821 }
2822 callee_id := e.child(node, 0)
2823 callee := e.node(callee_id)
2824 if value := e.disabled_call_value(node, callee) {
2825 return FlowSignal{
2826 values: [value]
2827 }
2828 }
2829 if callee.kind == .ident {
2830 fn_name := callee.value
2831 found := e.lookup_var(fn_name)
2832 if found.found && found.value is FnValue {
2833 fv := found.value as FnValue
2834 args_signal := e.eval_call_arg_values(node, e.fn_value_param_type_names(fv))!
2835 if args_signal.kind != .normal {
2836 return args_signal
2837 }
2838 result := e.call_fn_value(fv, args_signal.values)!
2839 e.write_back_fn_value(callee_id, result)!
2840 e.write_back_mutated_arg_values(node, result.mutated_args, args_signal.mut_lvalues)!
2841 return FlowSignal{
2842 values: [e.call_result_value(result)]
2843 }
2844 }
2845 expected_types := if target := e.function_def(e.current_module_name(), fn_name) {
2846 e.function_param_type_names(target, 0)
2847 } else {
2848 []string{}
2849 }
2850 args_signal := e.eval_call_arg_values(node, expected_types)!
2851 if args_signal.kind != .normal {
2852 return args_signal
2853 }
2854 result := e.call_function(e.current_module_name(), fn_name, args_signal.values)!
2855 e.write_back_mutated_args(node, result, args_signal.mut_lvalues)!
2856 return FlowSignal{
2857 values: [e.call_result_value(result)]
2858 }
2859 }
2860 if callee.kind == .selector {
2861 receiver_id := e.child(callee, 0)
2862 receiver_resolved := e.resolve_lvalue_flow(receiver_id)!
2863 if receiver_resolved.signal.kind != .normal {
2864 return receiver_resolved.signal
2865 }
2866 left := receiver_resolved.value
2867 if left is ModuleValue {
2868 expected_types := if target := e.function_def(left.name, callee.value) {
2869 e.function_param_type_names(target, 0)
2870 } else {
2871 []string{}
2872 }
2873 args_signal := e.eval_call_arg_values(node, expected_types)!
2874 if args_signal.kind != .normal {
2875 return args_signal
2876 }
2877 result := e.call_function(left.name, callee.value, args_signal.values)!
2878 e.write_back_mutated_args(node, result, args_signal.mut_lvalues)!
2879 return FlowSignal{
2880 values: [e.call_result_value(result)]
2881 }
2882 }
2883 if left is TypeValue {
2884 static_name := '${left.name.all_after_last('.')}.${callee.value}'
2885 static_module := e.type_value_module_name(left)
2886 expected_types := if target := e.function_def(static_module, static_name) {
2887 e.function_param_type_names(target, 0)
2888 } else {
2889 []string{}
2890 }
2891 args_signal := e.eval_call_arg_values(node, expected_types)!
2892 if args_signal.kind != .normal {
2893 return args_signal
2894 }
2895 result := e.call_function(static_module, static_name, args_signal.values)!
2896 e.write_back_mutated_args(node, result, args_signal.mut_lvalues)!
2897 return FlowSignal{
2898 values: [e.call_result_value(result)]
2899 }
2900 }
2901 selector_value := e.eval_selector_value(left, callee.value) or { void_value() }
2902 if selector_value is FnValue {
2903 args_signal :=
2904 e.eval_call_arg_values(node, e.fn_value_param_type_names(selector_value))!
2905 if args_signal.kind != .normal {
2906 return args_signal
2907 }
2908 result := e.call_fn_value(selector_value, args_signal.values)!
2909 e.write_back_fn_value(callee_id, result)!
2910 e.write_back_mutated_arg_values(node, result.mutated_args, args_signal.mut_lvalues)!
2911 return FlowSignal{
2912 values: [e.call_result_value(result)]
2913 }
2914 }
2915 receiver_type_name := e.infer_expr_type_name(receiver_id)
2916 expected_types := e.method_call_param_type_names(left, receiver_type_name, callee.value)
2917 args_signal := e.eval_call_arg_values(node, expected_types)!
2918 if args_signal.kind != .normal {
2919 return args_signal
2920 }
2921 result := e.call_value_method(left, receiver_type_name, callee.value, args_signal.values)!
2922 if result.receiver_changed {
2923 if e.is_assignable_target(receiver_id) {
2924 write_signal := e.write_resolved_lvalue_flow(receiver_resolved, result.receiver)!
2925 if write_signal.kind != .normal {
2926 return write_signal
2927 }
2928 }
2929 }
2930 e.write_back_mutated_arg_values(node, result.mutated_args, args_signal.mut_lvalues)!
2931 return FlowSignal{
2932 values: [result.value]
2933 }
2934 }
2935 if callee.kind == .fn_literal {
2936 fv := e.eval_fn_literal(callee_id, callee)!
2937 args_signal := e.eval_call_arg_values(node, e.fn_literal_param_type_names(callee))!
2938 if args_signal.kind != .normal {
2939 return args_signal
2940 }
2941 result := e.call_fn_value(fv, args_signal.values)!
2942 e.write_back_mutated_arg_values(node, result.mutated_args, args_signal.mut_lvalues)!
2943 return FlowSignal{
2944 values: [e.call_result_value(result)]
2945 }
2946 }
2947 value := e.eval_expr(callee_id)!
2948 if value is FnValue {
2949 args_signal := e.eval_call_arg_values(node, e.fn_value_param_type_names(value))!
2950 if args_signal.kind != .normal {
2951 return args_signal
2952 }
2953 result := e.call_fn_value(value, args_signal.values)!
2954 e.write_back_fn_value(callee_id, result)!
2955 e.write_back_mutated_arg_values(node, result.mutated_args, args_signal.mut_lvalues)!
2956 return FlowSignal{
2957 values: [e.call_result_value(result)]
2958 }
2959 }
2960 _ = id
2961 return error('v3.eval: unsupported call target `${callee.kind}`')
2962}
2963
2964fn (mut e Eval) disabled_call_value(call_node &flat.Node, callee &flat.Node) ?Value {
2965 match callee.kind {
2966 .ident {
2967 found := e.lookup_var(callee.value)
2968 if found.found && found.value is FnValue {
2969 return none
2970 }
2971 if value := e.disabled_function_zero_value(e.current_module_name(), callee.value,
2972 call_node)
2973 {
2974 return value
2975 }
2976 }
2977 .selector {
2978 if callee.children_count == 0 {
2979 return none
2980 }
2981 base_id := e.child(callee, 0)
2982 base := e.node(base_id)
2983 receiver_type := e.infer_expr_type_name(base_id)
2984 if receiver_type.len > 0 {
2985 if target := e.resolve_method_target(receiver_type, callee.value) {
2986 if e.is_disabled_fn_name_in_module(target.module_name, target.name) {
2987 return e.zero_value_for_disabled_function(call_node, target)
2988 }
2989 }
2990 }
2991 if base.kind == .ident {
2992 full_name := '${base.value}.${callee.value}'
2993 if value := e.disabled_function_zero_value(e.current_module_name(), full_name,
2994 call_node)
2995 {
2996 return value
2997 }
2998 found := e.lookup_var(base.value)
2999 if !found.found {
3000 module_name := e.resolve_module_name(base.value)
3001 if value := e.disabled_function_zero_value(module_name, callee.value, call_node) {
3002 return value
3003 }
3004 }
3005 }
3006 }
3007 else {}
3008 }
3009
3010 return none
3011}
3012
3013fn (e &Eval) function_def(module_name string, fn_name string) ?FunctionDef {
3014 target_module := if module_name == '' { e.current_module_name() } else { module_name }
3015 if target_module !in e.functions {
3016 return none
3017 }
3018 if fn_name in e.functions[target_module] {
3019 return e.functions[target_module][fn_name]
3020 }
3021 if target_module !in ['main', 'builtin'] && !fn_name.contains('.') {
3022 qualified := '${target_module}.${fn_name}'
3023 if qualified in e.functions[target_module] {
3024 return e.functions[target_module][qualified]
3025 }
3026 }
3027 return none
3028}
3029
3030fn (e &Eval) function_param_type_names(def FunctionDef, skip int) []string {
3031 node := e.node(def.node)
3032 mut types := []string{}
3033 mut param_index := 0
3034 for child_id in e.children(node) {
3035 child := e.node(child_id)
3036 if child.kind != .param {
3037 break
3038 }
3039 if param_index >= skip {
3040 types << e.qualify_expected_type_name(def.module_name, child.typ)
3041 }
3042 param_index++
3043 }
3044 return types
3045}
3046
3047fn (e &Eval) qualify_expected_type_name(module_name string, type_name string) string {
3048 name := type_name.trim_space()
3049 if name == '' {
3050 return ''
3051 }
3052 if name.starts_with('&') {
3053 return '&${e.qualify_expected_type_name(module_name, name[1..])}'
3054 }
3055 if name.starts_with('...') {
3056 return '...${e.qualify_expected_type_name(module_name, name[3..])}'
3057 }
3058 if name.starts_with('mut ') {
3059 return '&${e.qualify_expected_type_name(module_name, name[4..])}'
3060 }
3061 return e.qualify_nested_type_name(module_name, name)
3062}
3063
3064fn (e &Eval) fn_value_param_type_names(fv FnValue) []string {
3065 return e.fn_literal_param_type_names_in_module(e.node(fv.node), fv.module_name)
3066}
3067
3068fn (e &Eval) fn_literal_param_type_names(node &flat.Node) []string {
3069 return e.fn_literal_param_type_names_in_module(node, e.current_module_name())
3070}
3071
3072fn (e &Eval) fn_literal_param_type_names_in_module(node &flat.Node, module_name string) []string {
3073 children := e.children(node)
3074 mut i := 0
3075 for i < children.len {
3076 child := e.node(children[i])
3077 if child.kind != .ident {
3078 break
3079 }
3080 i++
3081 }
3082 mut types := []string{}
3083 for i < children.len {
3084 child := e.node(children[i])
3085 if child.kind != .param {
3086 break
3087 }
3088 types << e.qualify_expected_type_name(module_name, child.typ)
3089 i++
3090 }
3091 return types
3092}
3093
3094fn (e &Eval) method_call_param_type_names(receiver Value, receiver_type_name string, method_name string) []string {
3095 static_type_name := e.normalize_type_name(receiver_type_name)
3096 if static_type_name.len > 0 {
3097 if target := e.resolve_method_target(static_type_name, method_name) {
3098 return e.function_param_type_names(target, 1)
3099 }
3100 }
3101 if receiver is StructValue {
3102 if target := e.resolve_method_target(receiver.type_name, method_name) {
3103 return e.function_param_type_names(target, 1)
3104 }
3105 }
3106 if receiver is ArrayValue {
3107 return e.array_method_param_type_names(receiver, method_name)
3108 }
3109 if receiver is MapValue {
3110 return e.map_method_param_type_names(receiver, method_name)
3111 }
3112 if receiver is SumValue {
3113 return e.method_call_param_type_names(receiver.payload, receiver.variant_name, method_name)
3114 }
3115 return []string{}
3116}
3117
3118fn (e &Eval) array_method_param_type_names(receiver ArrayValue, method_name string) []string {
3119 return match method_name {
3120 'contains', 'index' { [receiver.elem_type_name] }
3121 else { []string{} }
3122 }
3123}
3124
3125fn (e &Eval) map_method_param_type_names(receiver MapValue, method_name string) []string {
3126 return match method_name {
3127 'delete' { [receiver.key_type_name] }
3128 else { []string{} }
3129 }
3130}
3131
3132fn (mut e Eval) eval_call_arg_values(node &flat.Node, expected_types []string) !FlowSignal {
3133 mut args := []Value{}
3134 mut mut_lvalues := map[int]ResolvedLvalue{}
3135 for child_index in 1 .. node.children_count {
3136 arg_index := child_index - 1
3137 expected_type := call_arg_expected_type(expected_types, arg_index)
3138 value_expected_type := call_arg_value_expected_type(expected_type)
3139 arg_id := e.child(node, child_index)
3140 if expected_type.starts_with('&') && e.is_assignable_target(arg_id) {
3141 resolved := e.resolve_lvalue_flow(arg_id)!
3142 if resolved.signal.kind != .normal {
3143 return resolved.signal
3144 }
3145 args << resolved.value
3146 mut_lvalues[arg_index] = resolved
3147 continue
3148 }
3149 signal := e.eval_expr_flow_expected(arg_id, value_expected_type)!
3150 if signal.kind != .normal {
3151 return signal
3152 }
3153 args << flow_value(signal)
3154 }
3155 return FlowSignal{
3156 values: args
3157 mut_lvalues: mut_lvalues
3158 }
3159}
3160
3161fn call_arg_expected_type(expected_types []string, index int) string {
3162 if index < expected_types.len {
3163 typ := expected_types[index]
3164 if typ.starts_with('...') {
3165 return typ[3..]
3166 }
3167 return typ
3168 }
3169 if expected_types.len > 0 {
3170 last := expected_types[expected_types.len - 1]
3171 if last.starts_with('...') {
3172 return last[3..]
3173 }
3174 }
3175 return ''
3176}
3177
3178fn call_arg_value_expected_type(type_name string) string {
3179 name := type_name.trim_space()
3180 if name.starts_with('&') {
3181 return call_arg_value_expected_type(name[1..])
3182 }
3183 if name.starts_with('mut ') {
3184 return call_arg_value_expected_type(name[4..])
3185 }
3186 if name.starts_with('...') {
3187 return call_arg_value_expected_type(name[3..])
3188 }
3189 return name
3190}
3191
3192fn (mut e Eval) disabled_function_zero_value(module_name string, fn_name string, call_node &flat.Node) ?Value {
3193 target_module := if module_name == '' { e.current_module_name() } else { module_name }
3194 mut candidates := []string{cap: 3}
3195 candidates << fn_name
3196 if target_module.len > 0 && target_module !in ['main', 'builtin'] && !fn_name.contains('.') {
3197 candidates << '${target_module}.${fn_name}'
3198 }
3199 if target_module in e.functions {
3200 for candidate in candidates {
3201 if candidate in e.functions[target_module] {
3202 target := e.functions[target_module][candidate]
3203 if e.is_disabled_fn_name_in_module(target.module_name, target.name)
3204 || e.is_disabled_fn_name_in_module(target_module, candidate) {
3205 return e.zero_value_for_disabled_function(call_node, target)
3206 }
3207 }
3208 }
3209 }
3210 for candidate in candidates {
3211 if e.is_disabled_fn_name_in_module(target_module, candidate) {
3212 return e.zero_value_for_disabled_return_type(call_node.typ, target_module)
3213 }
3214 }
3215 return none
3216}
3217
3218fn (mut e Eval) zero_value_for_disabled_function(call_node &flat.Node, target FunctionDef) Value {
3219 target_node := e.node(target.node)
3220 return e.zero_value_for_disabled_return_type(if call_node.typ.len > 0 {
3221 call_node.typ
3222 } else {
3223 target_node.typ
3224 }, target.module_name)
3225}
3226
3227fn (mut e Eval) zero_value_for_disabled_return_type(return_type string, module_name string) Value {
3228 if return_type.len == 0 || return_type == 'void' {
3229 return void_value()
3230 }
3231 return e.zero_value_for_type_name_in_module(return_type, module_name)
3232}
3233
3234fn (e &Eval) is_disabled_fn_name_in_module(module_name string, fn_name string) bool {
3235 if fn_name in e.a.disabled_fns {
3236 return true
3237 }
3238 if !fn_name.contains('.') && module_name.len > 0 && module_name !in ['main', 'builtin'] {
3239 return '${module_name}.${fn_name}' in e.a.disabled_fns
3240 }
3241 return false
3242}
3243
3244fn (e &Eval) call_result_value(result CallResult) Value {
3245 if result.values.len == 1 {
3246 return result.values[0]
3247 }
3248 return TupleValue{
3249 values: result.values
3250 }
3251}
3252
3253fn (mut e Eval) write_back_mutated_args(node &flat.Node, result CallResult, mut_lvalues map[int]ResolvedLvalue) ! {
3254 e.write_back_mutated_arg_values(node, result.mutated_args, mut_lvalues)!
3255}
3256
3257fn (mut e Eval) adapt_return_values(values []Value, return_type string) []Value {
3258 return_types := split_multi_return_types(return_type)
3259 if return_types.len > 0 {
3260 mut adapted := []Value{cap: values.len}
3261 for i, value in values {
3262 adapted << if i < return_types.len {
3263 e.adapt_value_to_type_name(value, return_types[i])
3264 } else {
3265 value
3266 }
3267 }
3268 return adapted
3269 }
3270 if values.len == 1 && return_type.len > 0 {
3271 return [e.adapt_value_to_type_name(values[0], return_type)]
3272 }
3273 return values.clone()
3274}
3275
3276fn split_multi_return_types(return_type string) []string {
3277 if !return_type.starts_with('(') || !return_type.ends_with(')') {
3278 return []string{}
3279 }
3280 inner := return_type[1..return_type.len - 1]
3281 mut types := []string{}
3282 mut start := 0
3283 mut paren_depth := 0
3284 mut bracket_depth := 0
3285 for i := 0; i < inner.len; i++ {
3286 ch := inner[i]
3287 match ch {
3288 `(` {
3289 paren_depth++
3290 }
3291 `)` {
3292 if paren_depth > 0 {
3293 paren_depth--
3294 }
3295 }
3296 `[` {
3297 bracket_depth++
3298 }
3299 `]` {
3300 if bracket_depth > 0 {
3301 bracket_depth--
3302 }
3303 }
3304 `,` {
3305 if paren_depth == 0 && bracket_depth == 0 {
3306 types << inner[start..i].trim_space()
3307 start = i + 1
3308 }
3309 }
3310 else {}
3311 }
3312 }
3313 last := inner[start..].trim_space()
3314 if last.len > 0 {
3315 types << last
3316 }
3317 return if types.len > 1 { types } else { []string{} }
3318}
3319
3320fn (e &Eval) minimum_arg_count(params []flat.NodeId) int {
3321 if params.len == 0 {
3322 return 0
3323 }
3324 last_param := e.node(params[params.len - 1])
3325 if last_param.typ.starts_with('...') {
3326 return params.len - 1
3327 }
3328 return params.len
3329}
3330
3331fn (mut e Eval) bind_call_params(params []flat.NodeId, args []Value) ! {
3332 for i, param_id in params {
3333 param := e.node(param_id)
3334 if param.typ.starts_with('...') {
3335 elem_type := param.typ[3..]
3336 mut values := []Value{cap: if args.len > i { args.len - i } else { 0 }}
3337 for j := i; j < args.len; j++ {
3338 values << e.adapt_value_to_type_name(args[j], elem_type)
3339 }
3340 if param.value.len > 0 {
3341 e.declare_var_typed(param.value, ArrayValue{
3342 elem_type_name: elem_type
3343 values: values
3344 }, '[]${elem_type}')
3345 }
3346 return
3347 }
3348 if i < args.len {
3349 e.declare_var_typed(param.value, e.adapt_value_to_type_name(args[i], param.typ),
3350 param.typ)
3351 }
3352 }
3353}
3354
3355fn (mut e Eval) collect_mutated_param_args(params []flat.NodeId, args []Value) map[int]Value {
3356 mut mutated_args := map[int]Value{}
3357 for i, param_id in params {
3358 param := e.node(param_id)
3359 if param.value.len == 0 {
3360 continue
3361 }
3362 if param.typ.starts_with('...') {
3363 continue
3364 }
3365 found := e.lookup_var(param.value)
3366 if !found.found {
3367 continue
3368 }
3369 if param.typ.starts_with('&') {
3370 mutated_args[i] = found.value
3371 continue
3372 }
3373 if i < args.len && args[i] is FnValue && found.value is FnValue {
3374 fn_value := found.value as FnValue
3375 if fn_value.captures.len > 0 {
3376 mutated_args[i] = found.value
3377 }
3378 }
3379 }
3380 return mutated_args
3381}
3382
3383fn (mut e Eval) write_back_fn_value(callee_id flat.NodeId, result CallResult) ! {
3384 if result.fn_value_changed && e.is_assignable_target(callee_id) {
3385 e.update_target(callee_id, Value(result.fn_value))!
3386 }
3387}
3388
3389fn (mut e Eval) write_back_mutated_arg_values(node &flat.Node, mutated_args map[int]Value, mut_lvalues map[int]ResolvedLvalue) ! {
3390 for child_index := 1; child_index < node.children_count; child_index++ {
3391 arg_index := child_index - 1
3392 if arg_index !in mutated_args {
3393 continue
3394 }
3395 value := mutated_args[arg_index] or { continue }
3396 if resolved := mut_lvalues[arg_index] {
3397 signal := e.write_resolved_lvalue_flow(resolved, value)!
3398 if signal.kind != .normal {
3399 return error('v3.eval: unexpected `${signal.kind}` escaped mut argument writeback')
3400 }
3401 continue
3402 }
3403 arg_id := e.child(node, child_index)
3404 if e.is_assignable_target(arg_id) {
3405 e.update_target(arg_id, value)!
3406 }
3407 }
3408}
3409
3410fn (e &Eval) is_assignable_target(id flat.NodeId) bool {
3411 if int(id) < 0 {
3412 return false
3413 }
3414 node := e.node(id)
3415 return node.kind in [.ident, .selector, .index]
3416}
3417
3418fn (mut e Eval) call_fn_value(fv FnValue, args []Value) !CallResult {
3419 node := e.node(fv.node)
3420 mut params := []flat.NodeId{}
3421 mut body_start := 0
3422 children := e.children(node)
3423 for body_start < children.len {
3424 child := e.node(children[body_start])
3425 if child.kind != .ident {
3426 break
3427 }
3428 body_start++
3429 }
3430 for body_start < children.len {
3431 child_id := children[body_start]
3432 child := e.node(child_id)
3433 if child.kind == .param {
3434 params << child_id
3435 body_start++
3436 continue
3437 }
3438 break
3439 }
3440 e.open_scope()
3441 e.call_stack << CallFrame{
3442 module_name: fv.module_name
3443 file_name: fv.file_name
3444 fn_name: '<anonymous>'
3445 return_type: node.typ
3446 scope_idx: e.scopes.len - 1
3447 }
3448 for name, value in fv.captures {
3449 e.declare_var_typed(name, value, fv.capture_types[name] or { '' })
3450 }
3451 e.bind_call_params(params, args)!
3452 signal := e.exec_stmts(children[body_start..])!
3453 e.run_deferred_stmts()!
3454 mutated_args := e.collect_mutated_param_args(params, args)
3455 mut updated_fn_value := fv
3456 if fv.captures.len > 0 {
3457 mut captures := fv.captures.clone()
3458 for name, _ in fv.captures {
3459 found := e.lookup_var(name)
3460 if found.found {
3461 captures[name] = found.value
3462 }
3463 }
3464 updated_fn_value = FnValue{
3465 node: fv.node
3466 module_name: fv.module_name
3467 file_name: fv.file_name
3468 captures: captures
3469 capture_types: fv.capture_types.clone()
3470 }
3471 }
3472 adapted_values := if signal.kind == .return_ {
3473 e.adapt_return_values(signal.values, node.typ)
3474 } else {
3475 []Value{}
3476 }
3477 e.close_scope()!
3478 e.call_stack.delete(e.call_stack.len - 1)
3479 if signal.kind == .return_ {
3480 return CallResult{
3481 values: adapted_values
3482 mutated_args: mutated_args
3483 fn_value_changed: fv.captures.len > 0
3484 fn_value: updated_fn_value
3485 }
3486 }
3487 if signal.kind != .normal {
3488 return error('v3.eval: unexpected `${signal.kind}` escaped anonymous function')
3489 }
3490 return CallResult{
3491 values: [void_value()]
3492 mutated_args: mutated_args
3493 fn_value_changed: fv.captures.len > 0
3494 fn_value: updated_fn_value
3495 }
3496}
3497
3498fn (mut e Eval) eval_selector(node &flat.Node) !Value {
3499 left := e.eval_expr(e.child(node, 0))!
3500 return e.eval_selector_value(left, node.value)
3501}
3502
3503fn (mut e Eval) eval_selector_value(left Value, field string) !Value {
3504 match left {
3505 ModuleValue {
3506 if value := e.lookup_const(left.name, field) {
3507 return value
3508 }
3509 return TypeValue{
3510 name: '${left.name}.${field}'
3511 }
3512 }
3513 TypeValue {
3514 if field == 'name' {
3515 return Value(left.name)
3516 }
3517 mod := e.type_value_module_name(left)
3518 enum_key := '${left.name.all_after_last('.')}.${field}'
3519 if value := e.lookup_const(mod, enum_key) {
3520 return e.enum_value(left.name, value)
3521 }
3522 if value := e.lookup_const(mod, field) {
3523 return e.enum_value(left.name, value)
3524 }
3525 return TypeValue{
3526 name: '${left.name}.${field}'
3527 }
3528 }
3529 ArrayValue {
3530 if field == 'len' {
3531 return Value(i64(left.values.len))
3532 }
3533 if field == 'cap' {
3534 return Value(i64(left.values.cap))
3535 }
3536 }
3537 MapValue {
3538 if field == 'len' {
3539 return Value(i64(left.entries.len))
3540 }
3541 }
3542 string {
3543 if field == 'len' {
3544 return Value(i64(left.len))
3545 }
3546 }
3547 StructValue {
3548 if field in left.fields {
3549 return left.fields[field] or { void_value() }
3550 }
3551 }
3552 SumValue {
3553 return e.eval_sum_selector(left, field)
3554 }
3555 else {}
3556 }
3557
3558 return error('v3.eval: unsupported selector `${field}` on `${e.runtime_type_name(left)}`')
3559}
3560
3561fn (e &Eval) eval_sum_selector(value SumValue, field string) !Value {
3562 if field == '_typ' {
3563 return Value(i64(e.sum_variant_index(value.type_name, value.variant_name)))
3564 }
3565 if value.payload is StructValue {
3566 payload := value.payload as StructValue
3567 if field in payload.fields {
3568 return payload.fields[field] or { void_value() }
3569 }
3570 }
3571 return error('v3.eval: unknown sum type field `${field}` on `${value.type_name}`')
3572}
3573
3574fn (e &Eval) sum_variant_index(type_name string, variant_name string) int {
3575 if type_name in e.sum_types {
3576 variants := e.sum_types[type_name]
3577 sum_module := if type_name.contains('.') {
3578 type_name.all_before_last('.')
3579 } else {
3580 e.current_module_name()
3581 }
3582 expected_name := e.qualify_type_name(sum_module, variant_name)
3583 for i, variant in variants {
3584 if variant == expected_name || variant == variant_name {
3585 return i
3586 }
3587 }
3588 mut short_match_index := -1
3589 for i, variant in variants {
3590 if variant.all_after_last('.') == variant_name.all_after_last('.') {
3591 if short_match_index >= 0 {
3592 return 0
3593 }
3594 short_match_index = i
3595 }
3596 }
3597 if short_match_index >= 0 {
3598 return short_match_index
3599 }
3600 }
3601 return 0
3602}
3603
3604fn (mut e Eval) eval_index(node &flat.Node) !Value {
3605 container := e.eval_expr(e.child(node, 0))!
3606 if node.value == 'range' {
3607 start := if node.children_count > 1 && e.node(e.child(node, 1)).kind != .empty {
3608 int(e.value_as_int(e.eval_expr(e.child(node, 1))!)!)
3609 } else {
3610 0
3611 }
3612 mut end := 0
3613 match container {
3614 ArrayValue { end = container.values.len }
3615 string { end = container.len }
3616 else {}
3617 }
3618
3619 if node.children_count > 2 {
3620 end = int(e.value_as_int(e.eval_expr(e.child(node, 2))!)!)
3621 }
3622 return e.slice_value(container, start, end)!
3623 }
3624 index := if container is MapValue {
3625 e.eval_expr_expected(e.child(node, 1), container.key_type_name)!
3626 } else {
3627 e.eval_expr(e.child(node, 1))!
3628 }
3629 return e.index_value(container, index)
3630}
3631
3632fn (mut e Eval) eval_index_flow(node &flat.Node) !FlowSignal {
3633 container_signal := e.eval_expr_flow(e.child(node, 0))!
3634 if container_signal.kind != .normal {
3635 return container_signal
3636 }
3637 container := flow_value(container_signal)
3638 if node.value == 'range' {
3639 mut start := 0
3640 if node.children_count > 1 && e.node(e.child(node, 1)).kind != .empty {
3641 start_signal := e.eval_expr_flow(e.child(node, 1))!
3642 if start_signal.kind != .normal {
3643 return start_signal
3644 }
3645 start = int(e.value_as_int(flow_value(start_signal))!)
3646 }
3647 mut end := 0
3648 match container {
3649 ArrayValue { end = container.values.len }
3650 string { end = container.len }
3651 else {}
3652 }
3653
3654 if node.children_count > 2 {
3655 end_signal := e.eval_expr_flow(e.child(node, 2))!
3656 if end_signal.kind != .normal {
3657 return end_signal
3658 }
3659 end = int(e.value_as_int(flow_value(end_signal))!)
3660 }
3661 return value_flow(e.slice_value(container, start, end)!)
3662 }
3663 index_signal := if container is MapValue {
3664 e.eval_expr_flow_expected(e.child(node, 1), container.key_type_name)!
3665 } else {
3666 e.eval_expr_flow(e.child(node, 1))!
3667 }
3668 if index_signal.kind != .normal {
3669 return index_signal
3670 }
3671 return value_flow(e.index_value(container, flow_value(index_signal))!)
3672}
3673
3674fn (mut e Eval) index_value(container Value, index Value) !Value {
3675 match container {
3676 ArrayValue {
3677 idx := int(e.value_as_int(index)!)
3678 if idx < 0 || idx >= container.values.len {
3679 return error('v3.eval: array index out of bounds')
3680 }
3681 return container.values[idx]
3682 }
3683 MapValue {
3684 value, ok := e.map_lookup(container, e.adapt_value_to_type_name(index,
3685 container.key_type_name))
3686 if ok {
3687 return value
3688 }
3689 return container.default_value
3690 }
3691 string {
3692 idx := int(e.value_as_int(index)!)
3693 if idx < 0 || idx >= container.len {
3694 return error('v3.eval: string index out of bounds')
3695 }
3696 return Value(i64(container[idx]))
3697 }
3698 else {
3699 return error('v3.eval: unsupported index target `${e.runtime_type_name(container)}`')
3700 }
3701 }
3702}
3703
3704fn (e &Eval) slice_value(container Value, start int, end int) !Value {
3705 match container {
3706 ArrayValue {
3707 mut arr := container
3708 arr.values = arr.values[start..end].clone()
3709 return arr
3710 }
3711 string {
3712 sliced := container[start..end]
3713 return Value(sliced)
3714 }
3715 else {
3716 return error('v3.eval: slicing is only supported for arrays and strings')
3717 }
3718 }
3719}
3720
3721fn (mut e Eval) eval_if_value(node &flat.Node) !Value {
3722 signal := e.eval_if_value_flow(node)!
3723 return flow_values_value(signal.values)
3724}
3725
3726fn (mut e Eval) eval_if_value_flow(node &flat.Node) !FlowSignal {
3727 return e.eval_if_value_flow_expected(node, '')
3728}
3729
3730fn (mut e Eval) eval_if_value_flow_expected(node &flat.Node, expected_type string) !FlowSignal {
3731 if node.children_count < 2 {
3732 return value_flow(void_value())
3733 }
3734 cond_id := e.child(node, 0)
3735 cond_is_guard := e.node(cond_id).kind == .decl_assign
3736 if cond_is_guard {
3737 e.open_scope()
3738 }
3739 cond_signal := e.eval_condition_flow(cond_id)!
3740 if cond_signal.kind != .normal {
3741 if cond_is_guard {
3742 e.close_scope()!
3743 }
3744 return cond_signal
3745 }
3746 if e.value_as_bool(flow_value(cond_signal))! {
3747 mut smartcast_scope := false
3748 if !cond_is_guard {
3749 if binding := e.smartcast_binding_from_condition(cond_id) {
3750 e.open_scope()
3751 e.declare_var_typed(binding.name, binding.value, binding.type_name)
3752 smartcast_scope = true
3753 }
3754 }
3755 signal := e.eval_value_expr_flow_expected(e.child(node, 1), expected_type)!
3756 if smartcast_scope {
3757 e.close_scope()!
3758 }
3759 if cond_is_guard {
3760 e.close_scope()!
3761 }
3762 return signal
3763 }
3764 if cond_is_guard {
3765 e.close_scope()!
3766 }
3767 if node.children_count > 2 {
3768 return e.eval_value_expr_flow_expected(e.child(node, 2), expected_type)
3769 }
3770 return value_flow(void_value())
3771}
3772
3773fn (mut e Eval) eval_value_expr_flow(id flat.NodeId) !FlowSignal {
3774 return e.eval_value_expr_flow_expected(id, '')
3775}
3776
3777fn (mut e Eval) eval_value_expr_flow_expected(id flat.NodeId, expected_type string) !FlowSignal {
3778 if int(id) >= 0 {
3779 node := e.node(id)
3780 if node.kind == .block {
3781 return e.eval_block_value_flow_expected(node, expected_type)
3782 }
3783 }
3784 return e.eval_expr_flow_expected(id, expected_type)
3785}
3786
3787fn (mut e Eval) eval_block_value(node &flat.Node) !Value {
3788 signal := e.eval_block_value_flow(node)!
3789 if signal.kind == .return_ && signal.values.len > 0 {
3790 return flow_values_value(signal.values)
3791 }
3792 return flow_values_value(signal.values)
3793}
3794
3795fn (mut e Eval) eval_block_value_flow(node &flat.Node) !FlowSignal {
3796 return e.eval_block_value_flow_expected(node, '')
3797}
3798
3799fn (mut e Eval) eval_block_value_flow_expected(node &flat.Node, expected_type string) !FlowSignal {
3800 return e.eval_block_value_flow_collect(node, false, expected_type)
3801}
3802
3803fn (mut e Eval) eval_block_value_flow_collect(node &flat.Node, collect_expr_values bool, expected_type string) !FlowSignal {
3804 e.open_scope()
3805 mut values := []Value{}
3806 for child_id in e.children(node) {
3807 child := e.node(child_id)
3808 if child.kind == .expr_stmt && child.children_count > 0 {
3809 expr_id := e.child(child, 0)
3810 expr := e.node(expr_id)
3811 if expr.kind == .infix && expr.op == .left_shift {
3812 signal := e.exec_stmt(child_id)!
3813 if signal.kind != .normal {
3814 e.close_scope()!
3815 return signal
3816 }
3817 continue
3818 }
3819 signal := e.eval_expr_flow_expected(expr_id, expected_type)!
3820 if signal.kind != .normal {
3821 e.close_scope()!
3822 return signal
3823 }
3824 expr_values := flow_values_or_void(signal.values)
3825 if collect_expr_values {
3826 for expr_value in expr_values {
3827 if expr_value !is VoidValue {
3828 values << expr_value
3829 }
3830 }
3831 } else {
3832 values = expr_values.clone()
3833 }
3834 continue
3835 }
3836 if child.kind == .block {
3837 collect_child_expr_values := node.children_count == 1
3838 && e.block_has_only_expr_stmts(child) && child.children_count > 1
3839 signal := e.eval_block_value_flow_collect(child, collect_child_expr_values,
3840 expected_type)!
3841 if signal.kind != .normal {
3842 e.close_scope()!
3843 return signal
3844 }
3845 values = flow_values_or_void(signal.values)
3846 continue
3847 }
3848 signal := e.exec_stmt(child_id)!
3849 if signal.kind != .normal {
3850 e.close_scope()!
3851 return signal
3852 }
3853 }
3854 e.close_scope()!
3855 return FlowSignal{
3856 values: flow_values_or_void(values)
3857 }
3858}
3859
3860fn (e &Eval) block_has_only_expr_stmts(node &flat.Node) bool {
3861 if node.children_count == 0 {
3862 return false
3863 }
3864 for child_id in e.children(node) {
3865 if e.node(child_id).kind != .expr_stmt {
3866 return false
3867 }
3868 }
3869 return true
3870}
3871
3872fn (mut e Eval) eval_array_init(node &flat.Node) !Value {
3873 return flow_value(e.eval_array_init_flow(node)!)
3874}
3875
3876fn (mut e Eval) eval_array_init_flow(node &flat.Node) !FlowSignal {
3877 array_type_name := if node.typ.len > 0 { node.typ } else { node.value }
3878 is_fixed_array := is_fixed_array_type_name(array_type_name)
3879 elem_type_name := if is_fixed_array {
3880 fixed_array_elem_type_name(array_type_name)
3881 } else {
3882 node.value
3883 }
3884 mut len := 0
3885 mut cap := 0
3886 mut has_cap := false
3887 mut init_id := flat.empty_node
3888 mut has_init := false
3889 mut values := []Value{}
3890 for child_id in e.children(node) {
3891 child := e.node(child_id)
3892 if child.kind == .field_init {
3893 if child.value == 'len' {
3894 signal := e.eval_expr_flow(e.child(child, 0))!
3895 if signal.kind != .normal {
3896 return signal
3897 }
3898 len = int(e.value_as_int(flow_value(signal))!)
3899 } else if child.value == 'cap' {
3900 signal := e.eval_expr_flow(e.child(child, 0))!
3901 if signal.kind != .normal {
3902 return signal
3903 }
3904 cap = int(e.value_as_int(flow_value(signal))!)
3905 has_cap = true
3906 } else if child.value == 'init' {
3907 init_id = e.child(child, 0)
3908 has_init = true
3909 }
3910 } else {
3911 signal := e.eval_expr_flow_expected(child_id, elem_type_name)!
3912 if signal.kind != .normal {
3913 return signal
3914 }
3915 values << e.adapt_value_to_type_name(flow_value(signal), elem_type_name)
3916 }
3917 }
3918 if len > 0 || has_cap {
3919 array_cap := if has_cap { cap } else { len }
3920 return e.eval_array_init_values(len, array_cap, has_init, init_id, elem_type_name)
3921 }
3922 if is_fixed_array && values.len == 0 {
3923 fixed_len := e.fixed_array_len(array_type_name)!
3924 return e.eval_array_init_values(fixed_len, fixed_len, has_init, init_id, elem_type_name)
3925 }
3926 return value_flow(ArrayValue{
3927 elem_type_name: elem_type_name
3928 values: values
3929 })
3930}
3931
3932fn (mut e Eval) eval_array_init_values(len int, cap int, has_init bool, init_id flat.NodeId, elem_type_name string) !FlowSignal {
3933 mut values := []Value{cap: cap}
3934 for i in 0 .. len {
3935 if has_init {
3936 e.open_scope()
3937 e.declare_var_typed('index', Value(i64(i)), 'int')
3938 signal := e.eval_expr_flow_expected(init_id, elem_type_name) or {
3939 e.close_scope()!
3940 return err
3941 }
3942 e.close_scope()!
3943 if signal.kind != .normal {
3944 return signal
3945 }
3946 values << e.adapt_value_to_type_name(flow_value(signal), elem_type_name)
3947 } else {
3948 values << e.zero_value_for_type_name(elem_type_name)
3949 }
3950 }
3951 return value_flow(ArrayValue{
3952 elem_type_name: elem_type_name
3953 values: values
3954 })
3955}
3956
3957fn is_fixed_array_type_name(type_name string) bool {
3958 if type_name.starts_with('[]') || type_name.starts_with('map[') {
3959 return false
3960 }
3961 return type_name.contains('[') && (type_name.ends_with(']') || type_name.starts_with('['))
3962}
3963
3964fn (mut e Eval) fixed_array_len(type_name string) !int {
3965 return e.fixed_array_len_in_module(type_name, e.current_module_name())
3966}
3967
3968fn (mut e Eval) fixed_array_len_in_module(type_name string, module_name string) !int {
3969 text := fixed_array_len_text(type_name)
3970 if len := fixed_array_len_literal(text) {
3971 return len
3972 }
3973 if value := e.lookup_const(module_name, text) {
3974 return int(e.value_as_int(value)!)
3975 }
3976 if text.contains('.') {
3977 mod_name := text.all_before_last('.')
3978 const_name := text.all_after_last('.')
3979 if value := e.lookup_const(mod_name, const_name) {
3980 return int(e.value_as_int(value)!)
3981 }
3982 }
3983 return 0
3984}
3985
3986fn fixed_array_len_literal(text string) ?int {
3987 normalized := text.replace('_', '')
3988 if normalized.len == 0 {
3989 return none
3990 }
3991 mut len := 0
3992 for ch in normalized {
3993 if ch < `0` || ch > `9` {
3994 return none
3995 }
3996 len = len * 10 + int(ch - `0`)
3997 }
3998 return len
3999}
4000
4001fn fixed_array_len_text(type_name string) string {
4002 return type_name.all_after('[').all_before(']').trim_space()
4003}
4004
4005fn fixed_array_elem_type_name(type_name string) string {
4006 if type_name.starts_with('[') {
4007 return type_name.all_after(']')
4008 }
4009 return type_name.all_before('[')
4010}
4011
4012fn (mut e Eval) eval_map_init(node &flat.Node) !Value {
4013 return flow_value(e.eval_map_init_flow(node)!)
4014}
4015
4016fn (mut e Eval) eval_map_init_flow(node &flat.Node) !FlowSignal {
4017 mut key_type, mut value_type := split_map_type(node.value)
4018 children := e.children(node)
4019 mut keys := []Value{}
4020 mut values := []Value{}
4021 mut i := 0
4022 for i + 1 < children.len {
4023 key_signal := e.eval_expr_flow_expected(children[i], key_type)!
4024 if key_signal.kind != .normal {
4025 return key_signal
4026 }
4027 key := flow_value(key_signal)
4028 if key_type.len == 0 {
4029 key_type = e.infer_expr_type_name(children[i])
4030 if key_type.len == 0 {
4031 key_type = e.runtime_type_name(key)
4032 }
4033 }
4034 typed_key := e.adapt_value_to_type_name(key, key_type)
4035 value_signal := e.eval_expr_flow_expected(children[i + 1], value_type)!
4036 if value_signal.kind != .normal {
4037 return value_signal
4038 }
4039 value := flow_value(value_signal)
4040 if value_type.len == 0 {
4041 value_type = e.infer_expr_type_name(children[i + 1])
4042 if value_type.len == 0 {
4043 value_type = e.runtime_type_name(value)
4044 }
4045 }
4046 keys << typed_key
4047 values << value
4048 i += 2
4049 }
4050 mut m := MapValue{
4051 key_type_name: key_type
4052 value_type_name: value_type
4053 default_value: e.zero_value_for_type_name(value_type)
4054 }
4055 for j, key in keys {
4056 m = e.map_set_value(m, key, values[j])
4057 }
4058 return value_flow(m)
4059}
4060
4061fn (mut e Eval) eval_string_interp_flow(node &flat.Node) !FlowSignal {
4062 mut out := ''
4063 for child_id in e.children(node) {
4064 child := e.node(child_id)
4065 if child.kind == .string_literal {
4066 out += child.value
4067 continue
4068 }
4069 signal := e.eval_expr_flow(child_id)!
4070 if signal.kind != .normal {
4071 return signal
4072 }
4073 out += e.display_string(flow_value(signal))!
4074 }
4075 return value_flow(Value(out))
4076}
4077
4078fn split_map_type(type_name string) (string, string) {
4079 if !type_name.starts_with('map[') {
4080 return '', ''
4081 }
4082 inner := type_name[4..]
4083 if idx := inner.index(']') {
4084 return inner[..idx], inner[idx + 1..]
4085 }
4086 return '', ''
4087}
4088
4089fn (mut e Eval) eval_struct_init(node &flat.Node) !Value {
4090 return flow_value(e.eval_struct_init_flow(node)!)
4091}
4092
4093fn (mut e Eval) eval_struct_init_flow(node &flat.Node) !FlowSignal {
4094 type_name := e.normalize_type_name(node.value)
4095 mut st := e.zero_struct_value(type_name)
4096 mut positional := 0
4097 for child_id in e.children(node) {
4098 child := e.node(child_id)
4099 if child.kind != .field_init {
4100 continue
4101 }
4102 if child.value.len > 0 {
4103 field_type := e.struct_field_type_name(st, child.value)
4104 value_signal := e.eval_expr_flow_expected(e.child(child, 0), field_type)!
4105 if value_signal.kind != .normal {
4106 return value_signal
4107 }
4108 value := flow_value(value_signal)
4109 st.fields[child.value] = e.adapt_value_to_type_name(value, e.struct_field_type_name(st,
4110 child.value))
4111 } else {
4112 fields := e.struct_fields(type_name)
4113 if positional < fields.len {
4114 field := fields[positional]
4115 field_type := e.qualify_nested_type_name(field.module_name, field.typ)
4116 value_signal := e.eval_expr_flow_expected(e.child(child, 0), field_type)!
4117 if value_signal.kind != .normal {
4118 return value_signal
4119 }
4120 value := flow_value(value_signal)
4121 st.fields[field.name] = e.adapt_value_to_type_name(value, field_type)
4122 }
4123 positional++
4124 }
4125 }
4126 return value_flow(st)
4127}
4128
4129fn (mut e Eval) eval_assoc(node &flat.Node) !Value {
4130 return flow_value(e.eval_assoc_flow(node)!)
4131}
4132
4133fn (mut e Eval) eval_assoc_flow(node &flat.Node) !FlowSignal {
4134 if node.children_count == 0 {
4135 return value_flow(e.zero_struct_value(node.value))
4136 }
4137 base_signal := e.eval_expr_flow(e.child(node, 0))!
4138 if base_signal.kind != .normal {
4139 return base_signal
4140 }
4141 base := flow_value(base_signal)
4142 if base !is StructValue {
4143 return error('v3.eval: assoc base must be struct')
4144 }
4145 mut st := base as StructValue
4146 for i in 1 .. node.children_count {
4147 field := e.child_node(node, i)
4148 if field.kind == .field_init {
4149 field_type := e.struct_field_type_name(st, field.value)
4150 value_signal := e.eval_expr_flow_expected(e.child(field, 0), field_type)!
4151 if value_signal.kind != .normal {
4152 return value_signal
4153 }
4154 st.fields[field.value] = e.adapt_value_to_type_name(flow_value(value_signal),
4155 field_type)
4156 }
4157 }
4158 return value_flow(st)
4159}
4160
4161fn (mut e Eval) eval_prefix(node &flat.Node) !Value {
4162 value := e.eval_expr(e.child(node, 0))!