Skip to main content

aver/interpreter/
exec.rs

1use super::*;
2
3impl Interpreter {
4    pub fn exec_items(&mut self, items: &[TopLevel]) -> Result<Value, RuntimeError> {
5        for item in items {
6            match item {
7                TopLevel::FnDef(fd) => self.exec_fn_def(fd)?,
8                TopLevel::Module(_) => {}
9                TopLevel::Verify(_) => {}
10                TopLevel::Decision(_) => {}
11                TopLevel::TypeDef(td) => self.register_type_def(td),
12                TopLevel::Stmt(s) => {
13                    self.exec_stmt(s)?;
14                }
15            }
16        }
17        Ok(Value::Unit)
18    }
19
20    /// Register a user-defined type: sum type variants and record constructors.
21    pub fn register_type_def(&mut self, td: &TypeDef) {
22        match td {
23            TypeDef::Sum {
24                name: type_name,
25                variants,
26                ..
27            } => {
28                if self.arena.find_type_id(type_name).is_none() {
29                    self.arena.register_sum_type(
30                        type_name,
31                        variants
32                            .iter()
33                            .map(|variant| variant.name.clone())
34                            .collect(),
35                    );
36                }
37                let mut members = HashMap::new();
38                for variant in variants {
39                    if variant.fields.is_empty() {
40                        // Zero-arg variant: stored directly as a Value
41                        members.insert(
42                            variant.name.clone(),
43                            Value::Variant {
44                                type_name: type_name.clone(),
45                                variant: variant.name.clone(),
46                                fields: vec![].into(),
47                            },
48                        );
49                    } else {
50                        // Constructor function
51                        members.insert(
52                            variant.name.clone(),
53                            Value::Builtin(format!("__ctor:{}:{}", type_name, variant.name)),
54                        );
55                    }
56                }
57                self.define(
58                    type_name.clone(),
59                    Value::Namespace {
60                        name: type_name.clone(),
61                        members,
62                    },
63                );
64            }
65            TypeDef::Product { name, fields, .. } => {
66                if self.arena.find_type_id(name).is_none() {
67                    self.arena.register_record_type(
68                        name,
69                        fields.iter().map(|(field, _)| field.clone()).collect(),
70                    );
71                }
72                // Product types are constructed via Expr::RecordCreate.
73                // Keep declaration field order so runtime records are canonicalized
74                // and positional record matches stay stable.
75                let schema = fields.iter().map(|(field, _)| field.clone()).collect();
76                self.record_schemas.insert(name.clone(), schema);
77            }
78        }
79    }
80
81    pub fn exec_fn_def(&mut self, fd: &FnDef) -> Result<(), RuntimeError> {
82        let lower_ctx = super::ir_bridge::InterpreterLowerCtx::new(self);
83        let val = Value::Fn(Rc::new(crate::value::FunctionValue {
84            name: Rc::new(fd.name.clone()),
85            params: Rc::new(fd.params.clone()),
86            return_type: Rc::new(fd.return_type.clone()),
87            effects: Rc::new(fd.effects.clone()),
88            body: Rc::clone(&fd.body),
89            lowered_body: super::lowered::lower_fn_body(fd.body.as_ref(), &lower_ctx, &fd.name),
90            resolution: fd.resolution.clone(),
91            memo_eligible: self.memo_fns.contains(&fd.name),
92            home_globals: None,
93        }));
94        self.define(fd.name.clone(), val);
95        Ok(())
96    }
97
98    pub fn exec_stmt(&mut self, stmt: &Stmt) -> Result<Value, RuntimeError> {
99        match stmt {
100            Stmt::Binding(name, _, expr) => {
101                let val = self.eval_expr(expr)?;
102                self.define(name.clone(), val);
103                Ok(Value::Unit)
104            }
105            Stmt::Expr(expr) => self.eval_expr(expr),
106        }
107    }
108
109    pub fn exec_body(&mut self, stmts: &[Stmt]) -> Result<Value, RuntimeError> {
110        let mut last = Value::Unit;
111        for stmt in stmts {
112            last = self.exec_stmt(stmt)?;
113        }
114        Ok(last)
115    }
116
117    pub fn run_file(&mut self, source: &str) -> Result<Value, RuntimeError> {
118        let mut items = parse_source(source).map_err(RuntimeError::Error)?;
119        crate::resolver::resolve_program(&mut items);
120
121        // First pass: register all top-level definitions
122        for item in &items {
123            match item {
124                TopLevel::FnDef(fd) => self.exec_fn_def(fd)?,
125                TopLevel::Stmt(s) => {
126                    self.exec_stmt(s)?;
127                }
128                _ => {}
129            }
130        }
131
132        // Second pass: run main() if it exists
133        let main_fn = self.lookup("main");
134        if let Ok(fn_val) = main_fn {
135            let allowed = Self::callable_declared_effects(&fn_val);
136            self.call_value_with_effects_pub(fn_val, vec![], "<main>", allowed)?;
137        }
138
139        Ok(Value::Unit)
140    }
141}