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::EffectSet { name, effects } => {
13                    self.register_effect_set(name.clone(), effects.clone());
14                }
15                TopLevel::Stmt(s) => {
16                    self.exec_stmt(s)?;
17                }
18            }
19        }
20        Ok(Value::Unit)
21    }
22
23    /// Register a user-defined type: sum type variants and record constructors.
24    pub fn register_type_def(&mut self, td: &TypeDef) {
25        match td {
26            TypeDef::Sum {
27                name: type_name,
28                variants,
29                ..
30            } => {
31                let mut members = HashMap::new();
32                for variant in variants {
33                    if variant.fields.is_empty() {
34                        // Zero-arg variant: stored directly as a Value
35                        members.insert(
36                            variant.name.clone(),
37                            Value::Variant {
38                                type_name: type_name.clone(),
39                                variant: variant.name.clone(),
40                                fields: vec![],
41                            },
42                        );
43                    } else {
44                        // Constructor function
45                        members.insert(
46                            variant.name.clone(),
47                            Value::Builtin(format!("__ctor:{}:{}", type_name, variant.name)),
48                        );
49                    }
50                }
51                self.define(
52                    type_name.clone(),
53                    Value::Namespace {
54                        name: type_name.clone(),
55                        members,
56                    },
57                );
58            }
59            TypeDef::Product { name, fields, .. } => {
60                // Product types are constructed via Expr::RecordCreate.
61                // Keep declaration field order so runtime records are canonicalized
62                // and positional record matches stay stable.
63                let schema = fields.iter().map(|(field, _)| field.clone()).collect();
64                self.record_schemas.insert(name.clone(), schema);
65            }
66        }
67    }
68
69    pub fn exec_fn_def(&mut self, fd: &FnDef) -> Result<(), RuntimeError> {
70        let val = Value::Fn {
71            name: fd.name.clone(),
72            params: fd.params.clone(),
73            return_type: fd.return_type.clone(),
74            effects: self.expand_effects(&fd.effects),
75            body: Rc::clone(&fd.body),
76            resolution: fd.resolution.clone(),
77            memo_eligible: self.memo_fns.contains(&fd.name),
78            home_globals: None,
79        };
80        self.define(fd.name.clone(), val);
81        Ok(())
82    }
83
84    pub fn exec_stmt(&mut self, stmt: &Stmt) -> Result<Value, RuntimeError> {
85        match stmt {
86            Stmt::Binding(name, _, expr) => {
87                let val = self.eval_expr(expr)?;
88                self.define(name.clone(), val);
89                Ok(Value::Unit)
90            }
91            Stmt::Expr(expr) => self.eval_expr(expr),
92        }
93    }
94
95    pub fn exec_body(&mut self, stmts: &[Stmt]) -> Result<Value, RuntimeError> {
96        let mut last = Value::Unit;
97        for stmt in stmts {
98            last = self.exec_stmt(stmt)?;
99        }
100        Ok(last)
101    }
102
103    /// Execute a block body inside a resolved (Slots-based) function.
104    /// Val/Var/Assign use slot indices when available.
105    pub(super) fn exec_body_resolved(
106        &mut self,
107        stmts: &[Stmt],
108        local_slots: &HashMap<String, u16>,
109    ) -> Result<Value, RuntimeError> {
110        let mut last = Value::Unit;
111        for stmt in stmts {
112            last = self.exec_stmt_resolved(stmt, local_slots)?;
113        }
114        Ok(last)
115    }
116
117    pub(super) fn exec_stmt_resolved(
118        &mut self,
119        stmt: &Stmt,
120        local_slots: &HashMap<String, u16>,
121    ) -> Result<Value, RuntimeError> {
122        match stmt {
123            Stmt::Binding(name, _, expr) => {
124                let val = self.eval_expr(expr)?;
125                if let Some(&slot) = local_slots.get(name) {
126                    self.define_slot(slot, val);
127                } else {
128                    self.define(name.clone(), val);
129                }
130                Ok(Value::Unit)
131            }
132            Stmt::Expr(expr) => self.eval_expr(expr),
133        }
134    }
135
136    pub fn run_file(&mut self, source: &str) -> Result<Value, RuntimeError> {
137        let mut items = parse_source(source).map_err(RuntimeError::Error)?;
138        crate::resolver::resolve_program(&mut items);
139
140        // First pass: register all top-level definitions
141        for item in &items {
142            match item {
143                TopLevel::FnDef(fd) => self.exec_fn_def(fd)?,
144                TopLevel::Stmt(s) => {
145                    self.exec_stmt(s)?;
146                }
147                _ => {}
148            }
149        }
150
151        // Second pass: run main() if it exists
152        let main_fn = self.lookup("main");
153        if let Ok(fn_val) = main_fn {
154            let allowed = Self::callable_declared_effects(&fn_val);
155            self.call_value_with_effects_pub(fn_val, vec![], "<main>", allowed)?;
156        }
157
158        Ok(Value::Unit)
159    }
160}