Skip to main content

aver/interpreter/
exec.rs

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