mimium_lang/
interpreter.rs

1use std::cell::RefCell;
2/// A tree walk interpreter of mimium, primarily used for macro expansion.
3/// This macro system is based on the multi-stage programming paradigm, like MetaML, MetaOCaml, Scala3, where expressions can be evaluated at multiple stages.
4use std::rc::Rc;
5
6use itertools::Itertools;
7
8use crate::ast::{Expr, Literal, RecordField};
9use crate::compiler::EvalStage;
10use crate::interner::{ExprNodeId, Symbol, ToSymbol, TypeNodeId};
11use crate::pattern::{Pattern, TypedPattern};
12use crate::plugin::{MacroFunType, MacroFunction, MacroInfo};
13use crate::types::Type;
14use crate::utils::environment::{Environment, LookupRes};
15
16type ClosureContent<T> = (Environment<(T, EvalStage)>, Vec<Symbol>, ExprNodeId);
17pub trait ValueTrait {
18    fn make_closure(e: ExprNodeId, names: Vec<Symbol>, env: Environment<(Self, EvalStage)>) -> Self
19    where
20        Self: std::marker::Sized;
21    fn get_as_closure(self) -> Option<ClosureContent<Self>>
22    where
23        Self: std::marker::Sized;
24    fn make_fixpoint(name: Symbol, e: ExprNodeId) -> Self;
25    fn get_as_fixpoint(self) -> Option<(Symbol, ExprNodeId)>
26    where
27        Self: std::marker::Sized;
28    fn get_as_external_fn(self) -> Option<Rc<RefCell<dyn Fn(&[(Self, TypeNodeId)]) -> Self>>>
29    where
30        Self: std::marker::Sized;
31}
32pub struct Context<V>
33where
34    V: Clone + ValueTrait + std::fmt::Debug,
35{
36    pub stage: EvalStage,
37    pub env: Environment<(V, EvalStage)>,
38}
39
40///Trait for defining general reduction rules of Lambda calculus, independent of the primitive types, even if it is untyped.
41pub trait GeneralInterpreter {
42    type Value: Clone + ValueTrait + std::fmt::Debug;
43    fn interpret_expr(&mut self, ctx: &mut Context<Self::Value>, expr: ExprNodeId) -> Self::Value;
44    fn get_empty_val(&self) -> Self::Value;
45
46    /// Helper method to dereference Store values. Override this for types that support Store.
47    fn deref_store(&self, val: &Self::Value) -> Self::Value {
48        val.clone()
49    }
50
51    /// Helper method to wrap values in Store. Override this for types that support Store.
52    fn wrap_store(&self, val: Self::Value) -> Self::Value {
53        val
54    }
55    fn eval_in_new_env(
56        &mut self,
57        binds: &[(Symbol, Self::Value)],
58        ctx: &mut Context<Self::Value>,
59        e: ExprNodeId,
60    ) -> Self::Value {
61        ctx.env.extend();
62        let binds = binds
63            .iter()
64            .map(|(name, val)| {
65                let v = val.clone();
66                (*name, (v, ctx.stage))
67            })
68            .collect_vec();
69        ctx.env.add_bind(binds.as_slice());
70        let res = self.eval(ctx, e);
71        ctx.env.to_outer();
72        res
73    }
74    fn eval_with_closure_env(
75        &mut self,
76        binds: &[(Symbol, (Self::Value, TypeNodeId))],
77        mut ctx: Context<Self::Value>,
78        e: ExprNodeId,
79    ) -> Self::Value {
80        let binds = binds
81            .iter()
82            .map(|(name, val)| {
83                let (v, _ty) = val.clone();
84                (*name, (v, ctx.stage))
85            })
86            .collect_vec();
87        ctx.env.extend();
88        ctx.env.add_bind(binds.as_slice());
89        let res = self.eval(&mut ctx, e);
90        ctx.env.to_outer();
91        res
92    }
93    fn eval(&mut self, ctx: &mut Context<Self::Value>, expr: ExprNodeId) -> Self::Value {
94        match expr.to_expr() {
95            Expr::Var(name) => match ctx.env.lookup_cls(&name) {
96                LookupRes::Local((val, bounded_stage)) if ctx.stage == *bounded_stage => {
97                    self.deref_store(val)
98                }
99                LookupRes::UpValue(_, (val, bounded_stage)) if ctx.stage == *bounded_stage => {
100                    self.deref_store(val)
101                }
102                LookupRes::Global((val, bounded_stage))
103                    if ctx.stage == *bounded_stage || *bounded_stage == EvalStage::Persistent =>
104                {
105                    self.deref_store(val)
106                }
107                LookupRes::None => panic!("Variable {name} not found"),
108                LookupRes::Local((_, bounded_stage))
109                | LookupRes::UpValue(_, (_, bounded_stage))
110                | LookupRes::Global((_, bounded_stage)) => {
111                    panic!(
112                        "Variable {name} found, but stage mismatch: expected {:?}, found {:?}",
113                        ctx.stage, bounded_stage
114                    )
115                }
116            },
117            Expr::Let(
118                TypedPattern {
119                    pat: Pattern::Single(name),
120                    ..
121                },
122                e,
123                body,
124            ) => {
125                let v = self.eval(ctx, e);
126                log::trace!("letting {} at stage: {}", name, ctx.stage);
127                let empty = self.get_empty_val();
128                let wrapped_v = self.wrap_store(v);
129                body.map_or(empty, |e| {
130                    self.eval_in_new_env(&[(name, wrapped_v)], ctx, e)
131                })
132            }
133            Expr::Let(_, _, _) => {
134                panic!("Let with multiple patterns should be destructed before evaluation")
135            }
136            Expr::LetRec(typed_id, e, body) => {
137                let fixpoint = ValueTrait::make_fixpoint(typed_id.id, e);
138                log::trace!(
139                    "Creating fixpoint for {}, stage: {}",
140                    typed_id.id,
141                    ctx.stage
142                );
143                let res = self.eval_in_new_env(&[(typed_id.id, fixpoint)], ctx, e);
144
145                let empty = self.get_empty_val();
146                body.map_or(empty, |e| {
147                    self.eval_in_new_env(&[(typed_id.id, res)], ctx, e)
148                })
149            }
150            Expr::Lambda(names, _, body) => {
151                let names = names.iter().map(|name| name.id).collect_vec();
152                //todo: need to deep-copy the expr?
153                ValueTrait::make_closure(body, names, ctx.env.clone())
154            }
155            Expr::Apply(f, a) => {
156                let fv = self.eval(ctx, f);
157                let args = a
158                    .clone()
159                    .into_iter()
160                    .map(|arg| {
161                        (
162                            self.eval(ctx, arg),
163                            Type::Unknown.into_id_with_location(arg.to_location()),
164                        )
165                    })
166                    .collect::<Vec<_>>();
167                if let Some(ext_fn) = fv.clone().get_as_external_fn() {
168                    ext_fn.borrow()(args.as_slice())
169                } else if let Some((c_env, names, body)) = fv.clone().get_as_closure() {
170                    log::trace!("entering closure app with names: {names:?}");
171                    let binds = names.into_iter().zip(args).collect_vec();
172                    let new_ctx = Context {
173                        env: c_env,
174                        stage: ctx.stage,
175                    };
176                    self.eval_with_closure_env(binds.as_slice(), new_ctx, body)
177                } else if let Some((_, e)) = fv.get_as_fixpoint() {
178                    let new_app = Expr::Apply(e, a.clone()).into_id(expr.to_location());
179                    self.eval(ctx, new_app)
180                } else {
181                    panic!("apply to non-fuctional type")
182                }
183            }
184
185            _ => self.interpret_expr(ctx, expr),
186        }
187    }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub enum ValueToExprError {
192    CodeToExpr,
193    ClosureToExpr,
194    FixpointToExpr,
195    ExternalFnToExpr,
196}
197trait MultiStageInterpreter {
198    type Value: Clone + ValueTrait + std::fmt::Debug + TryInto<ExprNodeId, Error = ValueToExprError>;
199}
200
201#[derive(Clone)]
202pub struct ExtFunction {
203    name: Symbol,
204    f: Rc<RefCell<dyn Fn(&[(Value, TypeNodeId)]) -> Value>>,
205}
206impl ExtFunction {
207    pub fn new(name: Symbol, f: impl Fn(&[(Value, TypeNodeId)]) -> Value + 'static) -> Self {
208        ExtFunction {
209            name,
210            f: Rc::new(RefCell::new(f)),
211        }
212    }
213}
214impl std::fmt::Debug for ExtFunction {
215    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216        write!(f, "External function: {}", self.name)
217    }
218}
219/// Evalueated result of the expression. Theoritically, it can be tagless union because it is statically typed, but we use enum for better readability.
220#[derive(Clone, Debug)]
221pub enum Value {
222    ErrorV(ExprNodeId),
223    Unit,
224    Number(f64),
225    String(Symbol),
226    Array(Vec<Value>),
227    Record(Vec<(Symbol, Value)>),
228    Tuple(Vec<Value>),
229    Closure(ExprNodeId, Vec<Symbol>, Environment<(Value, EvalStage)>),
230    Fixpoint(Symbol, ExprNodeId),
231    Code(ExprNodeId),
232    ExternalFn(ExtFunction),
233    Store(Rc<RefCell<Value>>),
234}
235impl From<&Box<dyn MacroFunction>> for Value {
236    fn from(macro_fn: &Box<dyn MacroFunction>) -> Self {
237        Value::ExternalFn(ExtFunction {
238            name: macro_fn.get_name(),
239            f: macro_fn.get_fn().clone(),
240        })
241    }
242}
243impl ValueTrait for Value {
244    fn make_closure(
245        e: ExprNodeId,
246        names: Vec<Symbol>,
247        env: Environment<(Self, EvalStage)>,
248    ) -> Self {
249        // Create a closure value with the given expression, names, and environment
250        Value::Closure(e, names, env)
251    }
252
253    fn get_as_closure(self) -> Option<(Environment<(Self, EvalStage)>, Vec<Symbol>, ExprNodeId)> {
254        match self {
255            Value::Closure(e, names, env) => Some((env, names, e)),
256            _ => None,
257        }
258    }
259
260    fn make_fixpoint(name: Symbol, e: ExprNodeId) -> Self {
261        // Create a fixpoint value with the given expression
262        Value::Fixpoint(name, e)
263    }
264
265    fn get_as_fixpoint(self) -> Option<(Symbol, ExprNodeId)>
266    where
267        Self: std::marker::Sized,
268    {
269        match self {
270            Value::Fixpoint(name, e) => Some((name, e)),
271            _ => None,
272        }
273    }
274    fn get_as_external_fn(self) -> Option<Rc<RefCell<dyn Fn(&[(Self, TypeNodeId)]) -> Self>>> {
275        match self {
276            Value::ExternalFn(f) => Some(f.f.clone()),
277            _ => None,
278        }
279    }
280}
281
282impl TryInto<ExprNodeId> for Value {
283    type Error = ValueToExprError;
284
285    fn try_into(self) -> Result<ExprNodeId, Self::Error> {
286        match self {
287            Value::Number(e) => {
288                Ok(Expr::Literal(Literal::Float(e.to_string().to_symbol())).into_id_without_span())
289            }
290            Value::String(s) => Ok(Expr::Literal(Literal::String(s)).into_id_without_span()),
291            Value::Array(elements) => {
292                let elements = elements.into_iter().map(|v| v.try_into()).try_collect()?;
293                Ok(Expr::ArrayLiteral(elements).into_id_without_span())
294            }
295            Value::Record(fields) => {
296                let fields = fields
297                    .into_iter()
298                    .map(|(name, value)| {
299                        value
300                            .try_into()
301                            .map(|expr: ExprNodeId| RecordField { name, expr })
302                    })
303                    .try_collect()?;
304                Ok(Expr::RecordLiteral(fields).into_id_without_span())
305            }
306            Value::Tuple(elements) => {
307                let elements = elements.into_iter().map(|e| e.try_into()).try_collect()?;
308                Ok(Expr::Tuple(elements).into_id_without_span())
309            }
310            Value::Closure(_, _, _) => {
311                // Closure cannot be converted to ExprNodeId directly
312                Err(ValueToExprError::ClosureToExpr)
313            }
314            Value::Fixpoint(_, _) => {
315                // Fixpoint cannot be converted to ExprNodeId directly
316                Err(ValueToExprError::FixpointToExpr)
317            }
318            Value::Code(e) => Ok(e),
319            Value::ExternalFn(_) => {
320                // External function cannot be converted to ExprNodeId directly
321                Err(ValueToExprError::ExternalFnToExpr)
322            }
323            Value::Unit => Ok(Expr::Block(None).into_id_without_span()),
324            Value::ErrorV(e) => Ok(e),
325            Value::Store(store) => {
326                // Dereference the Store and convert the inner value
327                store.borrow().clone().try_into()
328            }
329        }
330    }
331}
332
333#[derive(Default)]
334pub struct StageInterpreter {}
335
336impl MultiStageInterpreter for StageInterpreter {
337    type Value = Value;
338}
339
340impl StageInterpreter {
341    /// Evaluate an address expression to get a mutable reference to a Store.
342    /// Handles Var, FieldAccess, ArrayAccess, and Proj recursively.
343    fn eval_address(&mut self, ctx: &mut Context<Value>, expr: ExprNodeId) -> Rc<RefCell<Value>> {
344        match expr.to_expr() {
345            Expr::Var(name) => {
346                // Look up the Store in the environment
347                match ctx.env.lookup_cls(&name) {
348                    LookupRes::Local((Value::Store(store), _))
349                    | LookupRes::UpValue(_, (Value::Store(store), _))
350                    | LookupRes::Global((Value::Store(store), _)) => store.clone(),
351                    _ => panic!("Assignment target must be a Store-bound variable: {name}"),
352                }
353            }
354            Expr::FieldAccess(base, field) => {
355                let base_store = self.eval_address(ctx, base);
356                let base_val = base_store.borrow();
357                match &*base_val {
358                    Value::Record(fields) => fields
359                        .iter()
360                        .filter_map(|(name, v)| match (name, v) {
361                            (n, Value::Store(s)) if *n == field => Some(s.clone()),
362                            _ => None,
363                        })
364                        .next()
365                        .unwrap_or_else(|| panic!("Field {field} not found in record")),
366                    _ => panic!("Field access on non-record type"),
367                }
368            }
369            Expr::ArrayAccess(base, idx) => {
370                let base_store = self.eval_address(ctx, base);
371                let idx_val = self.eval(ctx, idx);
372                let base_val = base_store.borrow();
373                match (&*base_val, idx_val) {
374                    (Value::Array(elements), Value::Number(i)) => {
375                        if let Some(Value::Store(store)) = elements.get(i as usize) {
376                            store.clone()
377                        } else {
378                            log::error!("Array index {i} out of bounds or non-store was found");
379                            Rc::new(RefCell::new(Value::Number(0.0)))
380                        }
381                    }
382                    _ => panic!("Invalid value type detected. Possible bug in type checking."),
383                }
384            }
385            Expr::Proj(base, idx) => {
386                let base_store = self.eval_address(ctx, base);
387                let base_val = base_store.borrow();
388                match &*base_val {
389                    Value::Tuple(elements) => {
390                        if let Some(Value::Store(store)) = elements.get(idx as usize) {
391                            store.clone()
392                        } else {
393                            panic!("Tuple index {idx} out of bounds or non-store was found");
394                        }
395                    }
396                    _ => panic!("Projection on non-tuple type"),
397                }
398            }
399            _ => panic!("Invalid assignment target expression"),
400        }
401    }
402}
403
404impl GeneralInterpreter for StageInterpreter {
405    type Value = Value;
406
407    fn interpret_expr(&mut self, ctx: &mut Context<Value>, expr: ExprNodeId) -> Self::Value {
408        // Implement the logic for interpreting expressions here
409        if ctx.stage != EvalStage::Stage(0) {
410            Value::Code(self.rebuild(ctx, expr))
411        } else {
412            match expr.to_expr() {
413                Expr::ArrayLiteral(ev) => {
414                    let elements = ev.into_iter().map(|e| self.eval(ctx, e)).collect();
415                    Value::Array(elements)
416                }
417                Expr::RecordLiteral(fields) => {
418                    let evaluated_fields = fields
419                        .into_iter()
420                        .map(|RecordField { name, expr }| (name, self.eval(ctx, expr)))
421                        .collect();
422                    Value::Record(evaluated_fields)
423                }
424                Expr::Tuple(elements) => {
425                    let evaluated_elements =
426                        elements.into_iter().map(|e| self.eval(ctx, e)).collect();
427                    Value::Tuple(evaluated_elements)
428                }
429                Expr::Proj(e, idx) => {
430                    let evaluated_expr = self.eval(ctx, e);
431                    match evaluated_expr {
432                        Value::Tuple(elements) => {
433                            if idx < 0 || idx as usize >= elements.len() {
434                                panic!("Index out of bounds for tuple projection");
435                            }
436                            elements[idx as usize].clone()
437                        }
438                        _ => panic!("Projection can only be applied to tuples"),
439                    }
440                }
441                Expr::ArrayAccess(e, i) => {
442                    let evaluated_expr = self.eval(ctx, e);
443                    let evaluated_index = self.eval(ctx, i);
444                    match evaluated_expr {
445                        Value::Array(elements) => {
446                            if let Value::Number(idx) = evaluated_index {
447                                let idx = idx as usize;
448                                if idx < elements.len() {
449                                    elements[idx].clone()
450                                } else {
451                                    panic!("Index out of bounds for array access");
452                                }
453                            } else {
454                                panic!("Index must be a number for array access");
455                            }
456                        }
457                        _ => panic!("Array access can only be applied to arrays"),
458                    }
459                }
460                Expr::FieldAccess(e, name) => {
461                    let evaluated_expr = self.eval(ctx, e);
462                    match evaluated_expr {
463                        Value::Record(fields) => fields
464                            .into_iter()
465                            .find(|(field_name, _)| field_name == &name)
466                            .map_or_else(
467                                || panic!("Field {name} not found in record"),
468                                |(_, value)| value,
469                            ),
470                        _ => panic!("Field access can only be applied to records"),
471                    }
472                }
473                Expr::Block(e) => e.map_or(Value::Unit, |eid| self.eval_in_new_env(&[], ctx, eid)),
474                Expr::Literal(Literal::Float(f)) => Value::Number(f.to_string().parse().unwrap()),
475                Expr::Literal(Literal::Int(i)) => Value::Number(i as f64),
476                Expr::Literal(Literal::String(s)) => Value::String(s),
477                Expr::Literal(Literal::SelfLit) => {
478                    panic!("Self literal cannot be evaluated in macro expansion")
479                }
480                Expr::Literal(Literal::Now) => {
481                    panic!("Now literal cannot be evaluated in macro expansion")
482                }
483                Expr::Literal(Literal::SampleRate) => {
484                    panic!("Samplerate literal cannot be evaluated in macro expansion")
485                }
486                Expr::Error => Value::ErrorV(expr),
487                Expr::Feed(_, _) => {
488                    panic!("Feed expression cannot be evaluated in macro expansion")
489                }
490                Expr::BinOp(_, _, _) => {
491                    panic!("BinOp expression should be removed in the previous stage")
492                }
493                Expr::UniOp(_, _) => {
494                    panic!("UniOp expression should be removed in the previous stage")
495                }
496                Expr::If(cond, then, else_opt) => {
497                    let cond_val = self.eval(ctx, cond);
498                    match cond_val {
499                        Value::Number(n) if n > 0.0 => self.eval(ctx, then),
500                        Value::Number(_) => else_opt.map_or(Value::Unit, |e| self.eval(ctx, e)),
501                        _ => panic!("Condition must be a number for if expression"),
502                    }
503                }
504                Expr::Then(e1, e2) => {
505                    let _v1 = self.eval(ctx, e1);
506                    e2.map_or(Value::Unit, |e| self.eval(ctx, e))
507                }
508                Expr::Assign(target, e) => {
509                    // Evaluate the new value
510                    let new_val = self.eval(ctx, e);
511
512                    // Get the Store for the target
513                    let store = self.eval_address(ctx, target);
514                    *store.borrow_mut() = new_val;
515                    Value::Unit
516                }
517                Expr::Escape(_e) => {
518                    panic!("escape expression cannot be evaluated in stage 0")
519                }
520                Expr::Bracket(e) => {
521                    ctx.stage = EvalStage::Stage(1); // Increase the stage for bracket
522                    log::trace!("Bracketting expression, stage => {:?}", ctx.stage);
523
524                    let res = Value::Code(self.rebuild(ctx, e));
525                    ctx.stage = EvalStage::Stage(0); // Decrease the stage back
526                    res
527                }
528                // apply, lambda, let, letrec, escape, bracket, etc. will be handled by the interpreter trait
529                _ => self.eval(ctx, expr),
530            }
531        }
532    }
533
534    fn get_empty_val(&self) -> Self::Value {
535        Value::Unit
536    }
537
538    fn deref_store(&self, val: &Self::Value) -> Self::Value {
539        match val {
540            Value::Store(store) => store.borrow().clone(),
541            _ => val.clone(),
542        }
543    }
544
545    fn wrap_store(&self, val: Self::Value) -> Self::Value {
546        Value::Store(Rc::new(RefCell::new(val)))
547    }
548}
549
550impl StageInterpreter {
551    fn rebuild(&mut self, ctx: &mut Context<Value>, e: ExprNodeId) -> ExprNodeId {
552        match e.to_expr() {
553            Expr::Bracket(inner) => {
554                ctx.stage = ctx.stage.increment();
555                log::trace!("staging bracket expression, stage => {:?}", ctx.stage);
556                let res = self.rebuild(ctx, inner);
557                ctx.stage = ctx.stage.decrement();
558                res
559            }
560            Expr::Escape(inner) => {
561                ctx.stage = ctx.stage.decrement();
562                log::trace!("Unstaging escape expression, stage => {:?}", ctx.stage);
563
564                let v = self.eval(ctx, inner);
565                ctx.stage = ctx.stage.increment();
566                v.try_into()
567                    .expect("Failed to convert escape expression to ExprNodeId")
568            }
569            Expr::Apply(f, a) => {
570                let f_val = self.rebuild(ctx, f);
571                let a_vals = a.into_iter().map(|arg| self.rebuild(ctx, arg)).collect();
572                Expr::Apply(f_val, a_vals).into_id(e.to_location())
573            }
574            Expr::Lambda(params, r_ty, body) => {
575                let body_val = self.rebuild(ctx, body);
576                Expr::Lambda(params, r_ty, body_val).into_id(e.to_location())
577            }
578            Expr::Let(id, value, body) => Expr::Let(
579                id,
580                self.rebuild(ctx, value),
581                body.map(|b| self.rebuild(ctx, b)),
582            )
583            .into_id(e.to_location()),
584            Expr::LetRec(id, value, body) => Expr::LetRec(
585                id,
586                self.rebuild(ctx, value),
587                body.map(|b| self.rebuild(ctx, b)),
588            )
589            .into_id(e.to_location()),
590            Expr::Feed(id, body) => {
591                Expr::Feed(id, self.rebuild(ctx, body)).into_id(e.to_location())
592            }
593            Expr::If(cond, then, else_opt) => Expr::If(
594                self.rebuild(ctx, cond),
595                self.rebuild(ctx, then),
596                else_opt.map(|e| self.rebuild(ctx, e)),
597            )
598            .into_id(e.to_location()),
599            Expr::Then(e1, e2) => {
600                Expr::Then(self.rebuild(ctx, e1), e2.map(|e| self.rebuild(ctx, e)))
601                    .into_id(e.to_location())
602            }
603            Expr::Assign(target, value) => {
604                Expr::Assign(self.rebuild(ctx, target), self.rebuild(ctx, value))
605                    .into_id(e.to_location())
606            }
607            Expr::ArrayLiteral(elements) => {
608                Expr::ArrayLiteral(elements.into_iter().map(|e| self.rebuild(ctx, e)).collect())
609                    .into_id(e.to_location())
610            }
611            Expr::RecordLiteral(fields) => Expr::RecordLiteral(
612                fields
613                    .into_iter()
614                    .map(|RecordField { name, expr }| RecordField {
615                        name,
616                        expr: self.rebuild(ctx, expr),
617                    })
618                    .collect(),
619            )
620            .into_id(e.to_location()),
621            Expr::Tuple(elements) => {
622                Expr::Tuple(elements.into_iter().map(|e| self.rebuild(ctx, e)).collect())
623                    .into_id(e.to_location())
624            }
625            Expr::Proj(e, idx) => Expr::Proj(self.rebuild(ctx, e), idx).into_id(e.to_location()),
626            Expr::ArrayAccess(e, i) => {
627                Expr::ArrayAccess(self.rebuild(ctx, e), self.rebuild(ctx, i))
628                    .into_id(e.to_location())
629            }
630            Expr::FieldAccess(e, name) => {
631                Expr::FieldAccess(self.rebuild(ctx, e), name).into_id(e.to_location())
632            }
633            Expr::Block(b) => {
634                Expr::Block(b.map(|eid| self.rebuild(ctx, eid))).into_id(e.to_location())
635            }
636            _ => e,
637        }
638    }
639}
640
641pub fn create_default_interpreter(
642    extern_macros: &[Box<dyn MacroFunction>],
643) -> (StageInterpreter, Context<Value>) {
644    let mut env = Environment::new();
645
646    env.extend();
647    env.add_bind(
648        extern_macros
649            .iter()
650            .map(|m| {
651                (m.get_name(), (Value::from(m), EvalStage::Persistent)) // Stage is set to persistent for external functions
652            })
653            .collect::<Vec<_>>()
654            .as_slice(),
655    );
656    let ctx = Context {
657        stage: EvalStage::Stage(0),
658        env,
659    };
660    (StageInterpreter::default(), ctx)
661}
662
663/// Evaluate root expression. If the result value is not code, return original expression as is.
664/// if the result value is code, this function recursively evaluate the expression inside the code until the result becomes non-code.
665pub fn expand_macro(
666    expr: ExprNodeId,
667    top_type: TypeNodeId,
668    extern_macros: &[Box<dyn MacroFunction>],
669) -> ExprNodeId {
670    let (mut interpreter, mut ctx) = create_default_interpreter(extern_macros);
671    expand_macro_rec(expr, &mut ctx, &mut interpreter, top_type)
672}
673fn expand_macro_rec(
674    expr: ExprNodeId,
675    ctx: &mut Context<Value>,
676    interpreter: &mut StageInterpreter,
677    ty: TypeNodeId,
678) -> ExprNodeId {
679    if let Type::Code(t) = ty.to_type() {
680        let res = interpreter.eval(ctx, expr);
681        match res {
682            Value::Code(e) => {
683                ctx.stage = EvalStage::Stage(0);
684                expand_macro_rec(e, ctx, interpreter, t)
685            }
686            _ => panic!("macro expansion failed, possible typing error"),
687        }
688    } else {
689        expr
690    }
691}