Skip to main content

rl_lang/interpreter/utils/
statements.rs

1//! Statement evaluation - the main dispatch loop and control flow primitives.
2
3use crate::{
4    ast::statements::{FunctionAttribute, MatchPattern, Statement, StatementKind, TypeAnnotation},
5    interpreter::{
6        evaluator::Evaluator,
7        values::{FunctionData, Value},
8    },
9    lexer::tokenizer::Tokenizer,
10    parser::parser_logic::Parser,
11    utils::{errors::Error, source::SourceFile, span::Span},
12};
13use std::sync::Arc;
14use std::{path::Path, rc::Rc};
15
16impl Evaluator {
17    /// Evaluates a single statement, mutating the environment and control-flow flags.
18    ///
19    /// Loop control (`break`, `continue`) and function return (`return`) are signalled
20    /// via `is_breaking`, `is_continuing`, and `return_value` flags on [`Evaluator`]
21    /// rather than exceptions, so callers must check these flags after each statement.
22    pub fn evaluate_statement(&mut self, statement: &Statement) -> Result<(), Error> {
23        match &statement.kind {
24            StatementKind::RecordDeclaration { name, fields } => {
25                self.records.insert(name.clone(), fields.clone());
26            }
27            StatementKind::TagDeclaration { name, variants } => {
28                self.tags.insert(name.clone(), variants.clone());
29            }
30            StatementKind::ResolvedVariableDeclaration {
31                slot,
32                value,
33                type_annotation,
34                ..
35            } => {
36                let val = self.evaluate(*value)?;
37
38                let val_type = Self::infer_type(&val, false);
39                if !Self::types_compatible(&val_type, type_annotation)
40                    && val_type != *type_annotation
41                    && val_type != TypeAnnotation::Null
42                {
43                    return Err(self.err(
44                        format!(
45                            "type mismatch: expected {:?}, got {:?}",
46                            type_annotation, val_type
47                        ),
48                        statement.span,
49                    ));
50                }
51                self.insert_value(*slot, val, type_annotation.clone(), statement.span)?;
52            }
53
54            StatementKind::ResolvedConstantDeclaration {
55                slot,
56                value,
57                type_annotation,
58                ..
59            } => {
60                let val = self.evaluate(*value)?;
61
62                let val_type = Self::infer_type(&val, true);
63                if !Self::types_compatible(&val_type, type_annotation)
64                    && val_type != *type_annotation
65                    && val_type != TypeAnnotation::Null
66                {
67                    return Err(self.err(
68                        format!(
69                            "type mismatch: expected {:?}, got {:?}",
70                            type_annotation, val_type
71                        ),
72                        statement.span,
73                    ));
74                }
75                self.insert_const(*slot, val, type_annotation.clone(), statement.span)?;
76            }
77
78            StatementKind::ResolvedArray {
79                slot,
80                value,
81                type_annotation,
82                ..
83            } => {
84                let val = self.evaluate(*value)?;
85                let val = match val {
86                    Value::Values { items, .. } => {
87                        for item in &items {
88                            let actual = Self::infer_type(item, false);
89                            if !Self::types_compatible(&actual, type_annotation) {
90                                return Err(self.err(
91                                    format!(
92                                        "array element type mismatch: expected {:?}, found {:?}",
93                                        type_annotation, actual
94                                    ),
95                                    statement.span,
96                                ));
97                            }
98                        }
99                        Value::Values {
100                            items_type: type_annotation.clone(),
101                            items,
102                        }
103                    }
104                    other => {
105                        return Err(self.err(
106                            format!("expected array value found {}", other.type_name()),
107                            statement.span,
108                        ));
109                    }
110                };
111                let declared_type = TypeAnnotation::Array(Box::new(type_annotation.clone()));
112                self.insert_value(*slot, val, declared_type, statement.span)?;
113            }
114
115            StatementKind::ResolvedConstantArray {
116                slot,
117                value,
118                type_annotation,
119                ..
120            } => {
121                let val = self.evaluate(*value)?;
122                let val = match val {
123                    Value::Values { items, .. } => {
124                        for item in &items {
125                            let actual = Self::infer_type(item, false);
126                            if !Self::types_compatible(&actual, type_annotation) {
127                                return Err(self.err(
128                                    format!(
129                                        "array element type mismatch: expected {:?}, found {:?}",
130                                        type_annotation, actual
131                                    ),
132                                    statement.span,
133                                ));
134                            }
135                        }
136                        Value::Values {
137                            items_type: type_annotation.clone(),
138                            items,
139                        }
140                    }
141                    other => {
142                        return Err(self.err(
143                            format!("expected array value found {}", other.type_name()),
144                            statement.span,
145                        ));
146                    }
147                };
148                let declared_type = TypeAnnotation::CArray(Box::new(type_annotation.clone()));
149                self.insert_value(*slot, val, declared_type, statement.span)?;
150            }
151
152            StatementKind::ResolvedSet {
153                slot,
154                value,
155                type_annotation,
156                ..
157            } => {
158                let val = self.evaluate(*value)?;
159                let val = match val {
160                    Value::Set { items, .. } => {
161                        for item in &items {
162                            let actual = Self::infer_type(item, false);
163                            if !Self::types_compatible(&actual, type_annotation) {
164                                return Err(self.err(
165                                    format!(
166                                        "set element type mismatch: expected {:?}, found {:?}",
167                                        type_annotation, actual
168                                    ),
169                                    statement.span,
170                                ));
171                            }
172                        }
173                        Value::Set {
174                            items_type: type_annotation.clone(),
175                            items,
176                        }
177                    }
178                    other => {
179                        return Err(self.err(
180                            format!("expected set value found {}", other.type_name()),
181                            statement.span,
182                        ));
183                    }
184                };
185                let declared_type = TypeAnnotation::Set(Box::new(type_annotation.clone()));
186                self.insert_value(*slot, val, declared_type, statement.span)?;
187            }
188
189            StatementKind::ResolvedConstantSet {
190                slot,
191                value,
192                type_annotation,
193                ..
194            } => {
195                let val = self.evaluate(*value)?;
196                let val = match val {
197                    Value::Set { items, .. } => {
198                        for item in &items {
199                            let actual = Self::infer_type(item, false);
200                            if !Self::types_compatible(&actual, type_annotation) {
201                                return Err(self.err(
202                                    format!(
203                                        "set element type mismatch: expected {:?}, found {:?}",
204                                        type_annotation, actual
205                                    ),
206                                    statement.span,
207                                ));
208                            }
209                        }
210                        Value::Set {
211                            items_type: type_annotation.clone(),
212                            items,
213                        }
214                    }
215                    other => {
216                        return Err(self.err(
217                            format!("expected set value found {}", other.type_name()),
218                            statement.span,
219                        ));
220                    }
221                };
222                let declared_type = TypeAnnotation::CSet(Box::new(type_annotation.clone()));
223                self.insert_value(*slot, val, declared_type, statement.span)?;
224            }
225
226            StatementKind::ResolvedMap {
227                slot,
228                value,
229                type_annotation,
230                ..
231            } => {
232                let (declared_key, declared_value) = match type_annotation {
233                    TypeAnnotation::Map(k, v) => (k.as_ref().clone(), v.as_ref().clone()),
234                    other => (TypeAnnotation::Null, other.clone()),
235                };
236                let val = self.evaluate(*value)?;
237                let val = match val {
238                    Value::Map { entries, .. } => {
239                        for (_, v) in entries.borrow().iter() {
240                            let actual = Self::infer_type(v, false);
241                            if !Self::types_compatible(&actual, &declared_value) {
242                                return Err(self.err(
243                                    format!(
244                                        "map value type mismatch: expected {:?}, found {:?}",
245                                        declared_value, actual
246                                    ),
247                                    statement.span,
248                                ));
249                            }
250                        }
251                        Value::Map {
252                            key_type: declared_key.clone(),
253                            value_type: declared_value.clone(),
254                            entries,
255                        }
256                    }
257                    other => {
258                        return Err(self.err(
259                            format!("expected map value found {}", other.type_name()),
260                            statement.span,
261                        ));
262                    }
263                };
264                let declared_type =
265                    TypeAnnotation::Map(Box::new(declared_key), Box::new(declared_value));
266                self.insert_value(*slot, val, declared_type, statement.span)?;
267            }
268
269            StatementKind::ResolvedConstantMap {
270                slot,
271                value,
272                type_annotation,
273                ..
274            } => {
275                let (declared_key, declared_value) = match type_annotation {
276                    TypeAnnotation::CMap(k, v) => (k.as_ref().clone(), v.as_ref().clone()),
277                    other => (TypeAnnotation::Null, other.clone()),
278                };
279                let val = self.evaluate(*value)?;
280                let val = match val {
281                    Value::Map { entries, .. } => {
282                        for (_, v) in entries.borrow().iter() {
283                            let actual = Self::infer_type(v, false);
284                            if !Self::types_compatible(&actual, &declared_value) {
285                                return Err(self.err(
286                                    format!(
287                                        "map value type mismatch: expected {:?}, found {:?}",
288                                        declared_value, actual
289                                    ),
290                                    statement.span,
291                                ));
292                            }
293                        }
294                        Value::Map {
295                            key_type: declared_key.clone(),
296                            value_type: declared_value.clone(),
297                            entries,
298                        }
299                    }
300                    other => {
301                        return Err(self.err(
302                            format!("expected map value found {}", other.type_name()),
303                            statement.span,
304                        ));
305                    }
306                };
307                let declared_type =
308                    TypeAnnotation::CMap(Box::new(declared_key), Box::new(declared_value));
309                self.insert_const(*slot, val, declared_type, statement.span)?;
310            }
311
312            StatementKind::Expression(expr) => {
313                self.evaluate(*expr)?;
314            }
315
316            StatementKind::While { condition, body } => loop {
317                let condition_span = self.resolver.ast_arena.exprs.get(*condition).span;
318                let v = self.evaluate(*condition)?;
319                match v {
320                    Value::Bool(true) => {}
321                    Value::Bool(false) => break,
322                    other => {
323                        return Err(self
324                            .err("while condition must be a bool", statement.span)
325                            .with_label(
326                                condition_span,
327                                format!("this is {}, expected bool", other.type_name()),
328                            ));
329                    }
330                }
331                self.push_scope();
332                for statement in body {
333                    self.evaluate_statement(statement)?;
334                    if self.return_value.is_some() || self.is_breaking || self.is_continuing {
335                        break;
336                    }
337                }
338                self.pop_scope();
339                if self.is_breaking {
340                    self.is_breaking = false;
341                    break;
342                }
343
344                if self.is_continuing {
345                    self.is_continuing = false;
346                }
347
348                if self.return_value.is_some() {
349                    break;
350                }
351            },
352
353            StatementKind::Range(..) => {}
354
355            StatementKind::For {
356                initializer,
357                condition,
358                increment,
359                body,
360            } => {
361                self.push_scope();
362                self.evaluate_statement(initializer)?;
363                loop {
364                    let condition_span = self.resolver.ast_arena.exprs.get(*condition).span;
365                    let v = self.evaluate(*condition)?;
366                    match v {
367                        Value::Bool(true) => {}
368                        Value::Bool(false) => break,
369                        other => {
370                            return Err(self
371                                .err("for condition must be a bool", statement.span)
372                                .with_label(
373                                    condition_span,
374                                    format!("this is {}, expected bool", other.type_name()),
375                                ));
376                        }
377                    }
378
379                    for statement in body {
380                        self.evaluate_statement(statement)?;
381                        if self.return_value.is_some() || self.is_breaking || self.is_continuing {
382                            break;
383                        }
384                    }
385
386                    if self.is_breaking {
387                        self.is_breaking = false;
388                        break;
389                    }
390
391                    if self.is_continuing {
392                        self.is_continuing = false;
393                        self.evaluate(*increment)?;
394                        continue;
395                    }
396
397                    if self.return_value.is_some() {
398                        break;
399                    }
400
401                    self.evaluate(*increment)?;
402                }
403                self.pop_scope();
404            }
405
406            StatementKind::ResolvedFor {
407                initializer,
408                condition,
409                increment,
410                body,
411            } => {
412                self.evaluate_statement(initializer)?;
413                loop {
414                    let condition_span = self.resolver.ast_arena.exprs.get(*condition).span;
415                    let v = self.evaluate(*condition)?;
416                    match v {
417                        Value::Bool(true) => {}
418                        Value::Bool(false) => break,
419                        other => {
420                            return Err(self
421                                .err("for condition must be a bool", statement.span)
422                                .with_label(
423                                    condition_span,
424                                    format!("this is {}, expected bool", other.type_name()),
425                                ));
426                        }
427                    }
428
429                    for stmt in body {
430                        self.evaluate_statement(stmt)?;
431                        if self.return_value.is_some() || self.is_breaking || self.is_continuing {
432                            break;
433                        }
434                    }
435
436                    if self.is_breaking {
437                        self.is_breaking = false;
438                        break;
439                    }
440                    if self.is_continuing {
441                        self.is_continuing = false;
442                        self.evaluate(*increment)?;
443                        continue;
444                    }
445                    if self.return_value.is_some() {
446                        break;
447                    }
448
449                    self.evaluate(*increment)?;
450                }
451            }
452            StatementKind::Import { names, path } => {
453                let module_path = path.join("::");
454                let mut module = &self.root_module;
455                for seg in path {
456                    module = module.submodules.get(seg).ok_or_else(|| {
457                        self.err(format!("unknown module '{}'", seg), statement.span)
458                    })?;
459                }
460                let fns: Vec<_> = names
461                    .iter()
462                    .map(|name| {
463                        let f = module.functions.get(name).ok_or_else(|| {
464                            self.err(
465                                format!("'{}' is not defined in '{}'", name, module_path),
466                                statement.span,
467                            )
468                        })?;
469                        Ok((name.clone(), Arc::clone(f)))
470                    })
471                    .collect::<Result<_, Error>>()?;
472                for (name, f) in fns {
473                    self.root_module.functions.insert(name, f);
474                }
475            }
476
477            StatementKind::ResolvedImportFile { body, .. } => {
478                for stmt in body {
479                    self.evaluate_statement(stmt)?;
480                }
481            }
482
483            StatementKind::ImportFileNamed { path, names } => {
484                let import_name = format!("{}.rl", path.join("/"));
485                let file_path = if let Some(ref source_file) = self.source_file {
486                    let current_file_dir = Path::new(source_file.name.as_ref())
487                        .parent()
488                        .unwrap_or_else(|| Path::new(""));
489                    current_file_dir.join(&import_name)
490                } else {
491                    import_name.clone().into()
492                };
493
494                let source_text = std::fs::read_to_string(&file_path).map_err(|_| {
495                    self.err(
496                        format!("could not read file '{}'", import_name),
497                        statement.span,
498                    )
499                })?;
500                let source_file =
501                    SourceFile::new(file_path.to_string_lossy().as_ref(), source_text);
502                let tokens = Tokenizer::lex(source_file.clone())?;
503
504                let (file_ast, stmts) = Parser::parse(tokens, source_file.clone())?;
505                let stmts = self.resolver.ast_arena.merge_statements(file_ast, stmts);
506                let stmts = self.resolver.resolve_statements(stmts);
507
508                let previous_source = self.source_file.clone();
509                self.source_file = Some(source_file);
510
511                for stmt in &stmts {
512                    self.evaluate_statement(stmt)?;
513                }
514
515                let exported = self.environment.last().cloned().unwrap_or_default();
516
517                self.source_file = previous_source;
518
519                let _ = names; // TODO: filter by name once ScopeMap is threaded through
520                let no_scope_err = self.err("no active scope", statement.span);
521                let frame = self.environment.last_mut().ok_or(no_scope_err)?;
522                frame.extend(exported);
523            }
524
525            StatementKind::ResolvedForRange {
526                slot, range, body, ..
527            } => {
528                let items = match &range.kind {
529                    StatementKind::Range(items) => items.clone(),
530                    _ => {
531                        return Err(
532                            self.err("for-range: expected a range statement", statement.span)
533                        );
534                    }
535                };
536
537                for item in items {
538                    self.push_scope();
539                    self.insert_value(
540                        *slot,
541                        Value::Integer(item),
542                        crate::ast::statements::TypeAnnotation::Int,
543                        statement.span,
544                    )?;
545
546                    for statement in body {
547                        self.evaluate_statement(statement)?;
548                        if self.return_value.is_some() || self.is_breaking || self.is_continuing {
549                            break;
550                        }
551                    }
552
553                    self.pop_scope();
554
555                    if self.is_breaking {
556                        self.is_breaking = false;
557                        break;
558                    }
559
560                    if self.is_continuing {
561                        self.is_continuing = false;
562                    }
563
564                    if self.return_value.is_some() {
565                        break;
566                    }
567                }
568            }
569
570            StatementKind::ResolvedForEach {
571                slot,
572                iterable,
573                body,
574                ..
575            } => {
576                let iterable_span = self.resolver.ast_arena.exprs.get(*iterable).span;
577                let arr = self.evaluate(*iterable)?;
578                let items = match arr {
579                    Value::Values { items, .. } => items,
580                    other => {
581                        return Err(self
582                            .err("for-each: expected an array", statement.span)
583                            .with_label(
584                                iterable_span,
585                                format!("this is {}, expected array", other.type_name()),
586                            ));
587                    }
588                };
589                for item in items {
590                    let item_type = Evaluator::infer_type(&item, false);
591                    self.push_scope();
592                    self.insert_value(*slot, item, item_type, statement.span)?;
593
594                    for statement in body {
595                        self.evaluate_statement(statement)?;
596                        if self.return_value.is_some() || self.is_breaking || self.is_continuing {
597                            break;
598                        }
599                    }
600                    self.pop_scope();
601
602                    if self.is_breaking {
603                        self.is_breaking = false;
604                        break;
605                    }
606
607                    if self.is_continuing {
608                        self.is_continuing = false;
609                    }
610
611                    if self.return_value.is_some() {
612                        break;
613                    }
614                }
615            }
616
617            StatementKind::ConditionalBranch {
618                condition,
619                body,
620                needs_scope,
621            } => match condition {
622                Some(condition) => {
623                    let condition_span = self.resolver.ast_arena.exprs.get(*condition).span;
624                    let v = self.evaluate(*condition)?;
625                    match v {
626                        Value::Bool(true) => {}
627                        Value::Bool(false) => return Ok(()),
628                        other => {
629                            return Err(self
630                                .err("condition must be a bool", statement.span)
631                                .with_label(
632                                    condition_span,
633                                    format!("this is {}, expected bool", other.type_name()),
634                                ));
635                        }
636                    }
637                    if *needs_scope {
638                        self.push_scope();
639                    }
640                    for statement in body {
641                        self.evaluate_statement(statement)?;
642                        if self.return_value.is_some() || self.is_breaking || self.is_continuing {
643                            break;
644                        }
645                    }
646                    if *needs_scope {
647                        self.pop_scope();
648                    }
649                }
650                _ => {
651                    for statement in body {
652                        self.evaluate_statement(statement)?;
653                        if self.return_value.is_some() || self.is_breaking || self.is_continuing {
654                            break;
655                        }
656                    }
657                }
658            },
659
660            StatementKind::Conditional {
661                if_branch,
662                else_branch,
663            } => {
664                if !self.evaluate_branch(if_branch)?
665                    && let Some(branch) = else_branch
666                {
667                    self.evaluate_branch(branch)?;
668                }
669            }
670
671            StatementKind::ResolvedFunctionDeclaration {
672                slot,
673                params,
674                return_type,
675                body,
676                name,
677                ..
678            } => {
679                let func = Value::Function(Rc::new(FunctionData {
680                    params: Rc::new(params.clone()),
681                    body: Rc::new(body.clone()),
682                    return_type: Some(return_type.clone()),
683                    captured_env: vec![],
684                }));
685                self.fn_names.insert(name.clone(), *slot);
686                self.insert_value(
687                    *slot,
688                    func,
689                    crate::ast::statements::TypeAnnotation::Fn,
690                    statement.span,
691                )?;
692            }
693
694            StatementKind::Return(expr) => {
695                let value = match expr {
696                    Some(e) => self.evaluate(*e)?,
697                    None => Value::Null,
698                };
699
700                self.return_value = Some(value);
701            }
702
703            StatementKind::Break => {
704                self.is_breaking = true;
705            }
706
707            StatementKind::Continue => {
708                self.is_continuing = true;
709            }
710
711            StatementKind::ResolvedDestructureDeclaration {
712                bindings,
713                slots,
714                value,
715            } => {
716                let val = self.evaluate(*value)?;
717                let items = match val {
718                    Value::Tuple(items) => items,
719                    other => {
720                        return Err(self.err(
721                            format!(
722                                "expected tuple on right side of destructure, got {}",
723                                other.type_name()
724                            ),
725                            statement.span,
726                        ));
727                    }
728                };
729                if items.len() != bindings.len() {
730                    return Err(self.err(
731                        format!(
732                            "destructure mismatch: {} bindings but tuple has {} elements",
733                            bindings.len(),
734                            items.len()
735                        ),
736                        statement.span,
737                    ));
738                }
739                for ((type_annotation, _name), (slot, val)) in
740                    bindings.iter().zip(slots.iter().zip(items))
741                {
742                    let val = match (type_annotation, &val) {
743                        (TypeAnnotation::Int | TypeAnnotation::CInt, Value::Byte(b)) => {
744                            Value::Integer(*b as i64)
745                        }
746                        _ => val,
747                    };
748                    let val_type = Self::infer_type(&val, false);
749                    if !Self::types_compatible(&val_type, type_annotation)
750                        && val_type != *type_annotation
751                        && val_type != TypeAnnotation::Null
752                    {
753                        return Err(self.err(
754                            format!(
755                                "tuple element type mismatch: expected {:?}, got {:?}",
756                                type_annotation, val_type
757                            ),
758                            statement.span,
759                        ));
760                    }
761                    self.insert_value(*slot, val, type_annotation.clone(), statement.span)?;
762                }
763            }
764
765            StatementKind::Match { value, arms } => {
766                let val = self.evaluate(*value)?;
767                for (pattern, body) in arms {
768                    let matched = match pattern {
769                        MatchPattern::Wildcard => true,
770                        MatchPattern::Literal(expr) => {
771                            let pat_val = self.evaluate(*expr)?;
772                            val == pat_val
773                        }
774                    };
775                    if matched {
776                        self.evaluate_block(body)?;
777                        break;
778                    }
779                }
780            }
781
782            _ => {}
783        }
784        Ok(())
785    }
786
787    /// Evaluates a [`ConditionalBranch`] or [`Conditional`] and returns `true` if the
788    /// branch was taken (condition was true or it was an `else`).
789    fn evaluate_branch(&mut self, statement: &Statement) -> Result<bool, Error> {
790        match &statement.kind {
791            StatementKind::ConditionalBranch {
792                condition,
793                body,
794                needs_scope,
795            } => match condition {
796                Some(condition) => {
797                    let condition_span = self.resolver.ast_arena.exprs.get(*condition).span;
798                    let v = self.evaluate(*condition)?;
799                    match v {
800                        Value::Bool(true) => {
801                            if *needs_scope {
802                                self.push_scope();
803                            }
804                            for statement in body {
805                                self.evaluate_statement(statement)?;
806                                if self.return_value.is_some()
807                                    || self.is_breaking
808                                    || self.is_continuing
809                                {
810                                    break;
811                                }
812                            }
813                            if *needs_scope {
814                                self.pop_scope();
815                            }
816                            Ok(true)
817                        }
818                        Value::Bool(false) => Ok(false),
819                        other => Err(self
820                            .err("condition must be a bool", statement.span)
821                            .with_label(
822                                condition_span,
823                                format!("this is {}, expected bool", other.type_name()),
824                            )),
825                    }
826                }
827                None => {
828                    if *needs_scope {
829                        self.push_scope();
830                    }
831                    for statement in body {
832                        self.evaluate_statement(statement)?;
833                        if self.return_value.is_some() || self.is_breaking || self.is_continuing {
834                            break;
835                        }
836                    }
837                    if *needs_scope {
838                        self.pop_scope();
839                    }
840                    Ok(true)
841                }
842            },
843
844            StatementKind::Conditional {
845                if_branch,
846                else_branch,
847            } => {
848                if !self.evaluate_branch(if_branch)?
849                    && let Some(branch) = else_branch
850                {
851                    self.evaluate_branch(branch)?;
852                }
853
854                Ok(true)
855            }
856            _ => Err(self.err("expected conditional branch", statement.span)),
857        }
858    }
859
860    /// The top-level entry point for a full rl program.
861    ///
862    /// If a function is annotated `!#[entry]` or named `main`, only declarations
863    /// and imports are evaluated first, then that function is called with no arguments.
864    /// If no entry point exists, all statements are evaluated top-to-bottom (script mode).
865    ///
866    /// Returns an error if multiple `!#[entry]` functions are found.
867    pub fn evaluate_program(&mut self, statements: &[Statement]) -> Result<(), Error> {
868        let mut explicit_entry: Option<(Span, usize)> = None;
869        let mut main_entry: Option<(Span, usize)> = None;
870        let mut inits: Vec<(Span, usize)> = vec![];
871        let mut finals: Vec<(Span, usize)> = vec![];
872        let mut tests: Vec<(Span, usize)> = vec![];
873
874        for statement in statements {
875            if let StatementKind::FunctionDeclaration {
876                name, attribute, ..
877            }
878            | StatementKind::ResolvedFunctionDeclaration {
879                name, attribute, ..
880            } = &statement.kind
881            {
882                let slot = match &statement.kind {
883                    StatementKind::ResolvedFunctionDeclaration { slot, .. } => Some(*slot),
884                    _ => None,
885                };
886
887                match attribute {
888                    Some(FunctionAttribute::Entry) => {
889                        if explicit_entry.is_some() {
890                            return Err(
891                                self.err("multiple !#[entry] functions found", statement.span)
892                            );
893                        }
894                        if let Some(s) = slot {
895                            explicit_entry = Some((statement.span, s));
896                        }
897                    }
898
899                    Some(FunctionAttribute::Init) => {
900                        if let Some(s) = slot {
901                            inits.push((statement.span, s))
902                        }
903                    }
904                    Some(FunctionAttribute::Final) => {
905                        if let Some(s) = slot {
906                            finals.push((statement.span, s))
907                        }
908                    }
909                    Some(FunctionAttribute::Test) => {
910                        if let Some(s) = slot {
911                            tests.push((statement.span, s))
912                        }
913                    }
914
915                    &None => {
916                        if name == "main"
917                            && let Some(s) = slot
918                        {
919                            main_entry = Some((statement.span, s));
920                        }
921                    }
922                }
923            }
924        }
925
926        let entry = explicit_entry.or(main_entry);
927        let has_tests = !tests.is_empty();
928        let has_inits = !inits.is_empty();
929        let has_finals = !finals.is_empty();
930
931        let Some((entry_span, entry_slot)) = entry else {
932            for statement in statements {
933                self.evaluate_statement(statement)?;
934            }
935            return Ok(());
936        };
937
938        for statement in statements {
939            match &statement.kind {
940                StatementKind::ResolvedImportFile { .. }
941                | StatementKind::ResolvedFunctionDeclaration { .. }
942                | StatementKind::FunctionDeclaration { .. }
943                | StatementKind::Import { .. }
944                | StatementKind::ImportFile { .. }
945                | StatementKind::ImportFileNamed { .. }
946                | StatementKind::ResolvedVariableDeclaration { .. }
947                | StatementKind::ResolvedConstantDeclaration { .. }
948                | StatementKind::ResolvedArray { .. }
949                | StatementKind::ResolvedConstantArray { .. }
950                | StatementKind::ResolvedMap { .. }
951                | StatementKind::ResolvedConstantMap { .. }
952                | StatementKind::TagDeclaration { .. }
953                | StatementKind::RecordDeclaration { .. } => self.evaluate_statement(statement)?,
954                _ => {}
955            }
956        }
957
958        // order goes tests -> inits -> entry -> finals
959        if has_tests {
960            for test_func in tests {
961                let (func_span, func_slot) = test_func;
962                let func = self.get_value(0, func_slot, func_span)?;
963                self.call_value(func, vec![], func_span)?;
964            }
965        }
966
967        if has_inits {
968            for init_func in inits {
969                let (func_span, func_slot) = init_func;
970                let func = self.get_value(0, func_slot, func_span)?;
971                self.call_value(func, vec![], func_span)?;
972            }
973        }
974
975        let func = self.get_value(0, entry_slot, entry_span)?;
976        self.call_value(func, vec![], entry_span)?;
977
978        if has_finals {
979            for final_func in finals {
980                let (func_span, func_slot) = final_func;
981                let func = self.get_value(0, func_slot, func_span)?;
982                self.call_value(func, vec![], func_span)?;
983            }
984        }
985
986        Ok(())
987    }
988
989    /// Evaluates a list of statements inside a fresh scope, used for inline blocks.
990    pub fn evaluate_block(&mut self, statements: &[Statement]) -> Result<(), Error> {
991        self.push_scope();
992        for statement in statements {
993            self.evaluate_statement(statement)?;
994            if self.return_value.is_some() || self.is_breaking || self.is_continuing {
995                break;
996            }
997        }
998        self.pop_scope();
999        Ok(())
1000    }
1001}