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            effects: self.expand_effects(&fd.effects),
74            body: Rc::clone(&fd.body),
75            resolution: fd.resolution.clone(),
76            memo_eligible: self.memo_fns.contains(&fd.name),
77            home_globals: None,
78        };
79        self.define(fd.name.clone(), val);
80        Ok(())
81    }
82
83    pub fn exec_stmt(&mut self, stmt: &Stmt) -> Result<Value, RuntimeError> {
84        match stmt {
85            Stmt::Binding(name, _, expr) => {
86                let val = self.eval_expr(expr)?;
87                self.define(name.clone(), val);
88                Ok(Value::Unit)
89            }
90            Stmt::Expr(expr) => self.eval_expr(expr),
91        }
92    }
93
94    pub fn exec_body(&mut self, stmts: &[Stmt]) -> Result<Value, RuntimeError> {
95        let mut last = Value::Unit;
96        for stmt in stmts {
97            last = self.exec_stmt(stmt)?;
98        }
99        Ok(last)
100    }
101
102    /// Execute a block body inside a resolved (Slots-based) function.
103    /// Val/Var/Assign use slot indices when available.
104    pub(super) fn exec_body_resolved(
105        &mut self,
106        stmts: &[Stmt],
107        local_slots: &HashMap<String, u16>,
108    ) -> Result<Value, RuntimeError> {
109        let mut last = Value::Unit;
110        for stmt in stmts {
111            last = self.exec_stmt_resolved(stmt, local_slots)?;
112        }
113        Ok(last)
114    }
115
116    pub(super) fn exec_stmt_resolved(
117        &mut self,
118        stmt: &Stmt,
119        local_slots: &HashMap<String, u16>,
120    ) -> Result<Value, RuntimeError> {
121        match stmt {
122            Stmt::Binding(name, _, expr) => {
123                let val = self.eval_expr(expr)?;
124                if let Some(&slot) = local_slots.get(name) {
125                    self.define_slot(slot, val);
126                } else {
127                    self.define(name.clone(), val);
128                }
129                Ok(Value::Unit)
130            }
131            Stmt::Expr(expr) => self.eval_expr(expr),
132        }
133    }
134
135    pub fn run_file(&mut self, source: &str) -> Result<Value, RuntimeError> {
136        let mut items = parse_source(source).map_err(RuntimeError::Error)?;
137        crate::resolver::resolve_program(&mut items);
138
139        // First pass: register all top-level definitions
140        for item in &items {
141            match item {
142                TopLevel::FnDef(fd) => self.exec_fn_def(fd)?,
143                TopLevel::Stmt(s) => {
144                    self.exec_stmt(s)?;
145                }
146                _ => {}
147            }
148        }
149
150        // Second pass: run main() if it exists
151        let main_fn = self.lookup("main");
152        if let Ok(fn_val) = main_fn {
153            let allowed = Self::callable_declared_effects(&fn_val);
154            self.call_value_with_effects_pub(fn_val, vec![], "<main>", allowed)?;
155        }
156
157        Ok(Value::Unit)
158    }
159}