cl_interpret/
interpret.rs

1//! A work-in-progress tree walk interpreter for Conlang
2//!
3//! Currently, major parts of the interpreter are not yet implemented, and major parts will never be
4//! implemented in its current form. Namely, since no [ConValue] has a stable location, it's
5//! meaningless to get a pointer to one, and would be undefined behavior to dereference a pointer to
6//! one in any situation.
7
8use crate::constructor::Constructor;
9
10use super::*;
11use cl_ast::{ast_visitor::Visit, *};
12use std::borrow::Borrow;
13
14macro trace($($t:tt)*) {{
15    #[cfg(debug_assertions)]
16    if std::env::var("CONLANG_TRACE").is_ok() {
17        eprintln!($($t)*)
18    }
19}}
20
21/// A work-in-progress tree walk interpreter for Conlang
22pub trait Interpret {
23    /// Interprets this thing in the given [`Environment`].
24    ///
25    /// Everything returns a value!™
26    fn interpret(&self, env: &mut Environment) -> IResult<ConValue>;
27}
28
29impl Interpret for File {
30    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
31        trace!("// Running {}", self.name);
32        /// Sorts items
33        #[derive(Debug, Default)]
34        struct ItemSorter<'ast>(pub [Vec<&'ast Item>; 8]);
35        impl<'ast> Visit<'ast> for ItemSorter<'ast> {
36            fn visit_item(&mut self, i: &'ast Item) {
37                for stage in match &i.kind {
38                    ItemKind::Module(_) => [0].as_slice(),
39                    ItemKind::Use(_) => &[1, 6],
40                    ItemKind::Enum(_) | ItemKind::Struct(_) | ItemKind::Alias(_) => &[2],
41                    ItemKind::Function(_) => &[3, 7],
42                    ItemKind::Impl(_) => &[4],
43                    ItemKind::Const(_) | ItemKind::Static(_) => &[5],
44                } {
45                    self.0[*stage].push(i)
46                }
47            }
48        }
49
50        let mut items = ItemSorter::default();
51        items.visit_file(self);
52        for item in items.0.into_iter().flatten() {
53            item.interpret(env)?;
54        }
55
56        Ok(ConValue::Empty)
57    }
58}
59
60impl Interpret for Item {
61    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
62        match &self.kind {
63            ItemKind::Alias(item) => item.interpret(env),
64            ItemKind::Const(item) => item.interpret(env),
65            ItemKind::Static(item) => item.interpret(env),
66            ItemKind::Module(item) => item.interpret(env),
67            ItemKind::Function(item) => item.interpret(env),
68            ItemKind::Struct(item) => item.interpret(env),
69            ItemKind::Enum(item) => item.interpret(env),
70            ItemKind::Impl(item) => item.interpret(env),
71            ItemKind::Use(item) => item.interpret(env),
72        }
73    }
74}
75
76impl Interpret for Alias {
77    fn interpret(&self, _env: &mut Environment) -> IResult<ConValue> {
78        trace!("// TODO: {self}");
79        Ok(ConValue::Empty)
80    }
81}
82
83impl Interpret for Const {
84    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
85        let Const { name, ty: _, init } = self;
86        trace!("// Defining const {name}");
87
88        let init = init.as_ref().interpret(env)?;
89        env.insert(*name, init);
90        Ok(ConValue::Empty)
91    }
92}
93
94impl Interpret for Static {
95    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
96        let Static { mutable: _, name, ty: _, init } = self;
97        trace!("// Defining static {name}");
98
99        let init = init.as_ref().interpret(env)?;
100        env.insert(*name, init);
101        Ok(ConValue::Empty)
102    }
103}
104
105impl Interpret for Module {
106    // TODO: Keep modules around somehow, rather than putting them on the stack
107    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
108        let Self { name, file } = self;
109        trace!("// Defining module {name}");
110
111        let mut scope = env.frame(name.to_ref());
112
113        let out = match file {
114            Some(file) => file.interpret(&mut scope),
115            None => {
116                eprintln!("Module {name} specified, but not imported.");
117                Ok(ConValue::Empty)
118            }
119        };
120
121        let frame = scope
122            .pop_values()
123            .expect("Environment frames must be balanced");
124        env.insert(*name, ConValue::Module(frame.into()));
125
126        out
127    }
128}
129
130impl Interpret for Function {
131    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
132        trace!("// Defining fn {}", self.name);
133
134        // register the function in the current environment
135        env.insert_fn(self);
136        Ok(ConValue::Empty)
137    }
138}
139
140impl Interpret for Struct {
141    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
142        let Self { name, gens: _, kind } = self;
143        trace!("// Defining struct {name}");
144
145        let mut frame = env.frame(name.to_ref());
146
147        match kind {
148            StructKind::Empty => {
149                let cs = Constructor { arity: 0, name: *name };
150                frame.insert("call".into(), ConValue::TupleConstructor(cs));
151                frame.insert("__nmemb".into(), ConValue::Int(0));
152            }
153            StructKind::Tuple(args) => {
154                let cs = Constructor { arity: args.len() as _, name: *name };
155                frame.insert("call".into(), ConValue::TupleConstructor(cs));
156                frame.insert("__nmemb".into(), ConValue::Int(args.len() as _));
157            }
158            StructKind::Struct(members) => {
159                // TODO: more precise type checking of structs
160                for (idx, StructMember { vis: _, name: nm, ty: _ }) in members.iter().enumerate() {
161                    trace!("// Defining {name}::{nm}");
162                    frame.insert(*nm, ConValue::Int(idx as _));
163                }
164                frame.insert("__nmemb".into(), ConValue::Int(members.len() as _));
165            }
166        }
167
168        let frame = frame
169            .pop_values()
170            .expect("Environment frames must be balanced");
171
172        env.insert(*name, ConValue::Module(Box::new(frame)));
173        Ok(ConValue::Empty)
174    }
175}
176
177impl Interpret for Enum {
178    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
179        let Self { name, gens: _, variants } = self;
180        trace!("// Defining enum {name}");
181
182        let mut scope = env.frame(name.to_ref());
183        for (idx, Variant { name, kind, body }) in variants.iter().enumerate() {
184            match (kind, body) {
185                (StructKind::Empty, None) => scope.insert(*name, ConValue::Int(idx as _)),
186                (StructKind::Empty, Some(idx)) => {
187                    let idx = idx.interpret(&mut scope)?;
188                    scope.insert(*name, idx)
189                }
190                (StructKind::Tuple(args), None) => {
191                    let cs = Constructor { arity: args.len() as _, name: *name };
192                    let mut variant = scope.frame(name.to_ref());
193                    variant.insert("call".into(), ConValue::TupleConstructor(cs));
194                    variant.insert("__nmemb".into(), ConValue::Int(args.len() as _));
195                    let frame = variant
196                        .pop_values()
197                        .expect("Frame stack should remain balanced.");
198                    scope.insert(*name, ConValue::Module(Box::new(frame)));
199                }
200                (StructKind::Struct(_), None) => {}
201                _ => eprintln!("Well-formedness error in {self}"),
202            }
203        }
204        let frame = scope
205            .pop_values()
206            .expect("Frame stack should remain balanced.");
207        env.insert(*name, ConValue::Module(Box::new(frame)));
208        Ok(ConValue::Empty)
209    }
210}
211
212impl Interpret for Impl {
213    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
214        let Self {
215            gens: _,
216            target: ImplKind::Type(Ty { span, kind: TyKind::Path(name), .. }),
217            body,
218        } = self
219        else {
220            trace!("TODO: impl X for Ty");
221            return Ok(ConValue::Empty);
222        };
223        let mut frame = env.frame("impl");
224        body.interpret(&mut frame)?;
225
226        let frame = frame
227            .pop_values()
228            .expect("Environment frames must be balanced");
229        match assignment::addrof_path(env, name.parts.as_slice())
230            .map_err(|err| err.with_span(*span))?
231        {
232            ConValue::Module(m) => m.extend(frame),
233            other => eprintln!("TODO: impl for {other}"),
234        }
235        Ok(ConValue::Empty)
236    }
237}
238
239impl Interpret for Use {
240    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
241        let Self { absolute: _, tree } = self;
242        tree.interpret(env)
243    }
244}
245
246impl Interpret for UseTree {
247    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
248        // TODO: raw-bind use items
249        type Bindings = HashMap<Sym, ConValue>;
250        use std::collections::HashMap;
251
252        fn get_bindings(
253            tree: &UseTree,
254            env: &mut Environment,
255            bindings: &mut Bindings,
256        ) -> IResult<()> {
257            match tree {
258                UseTree::Tree(use_trees) => {
259                    for tree in use_trees {
260                        get_bindings(tree, env, bindings)?;
261                    }
262                }
263                UseTree::Path(PathPart::Ident(name), tree) => {
264                    let Ok(ConValue::Module(m)) = env.get(*name) else {
265                        Err(Error::TypeError())?
266                    };
267                    let mut scope = env.with_frame(name.to_ref(), *m);
268                    let out = get_bindings(tree, &mut scope, bindings);
269                    return out;
270                }
271                UseTree::Alias(name, alias) => {
272                    bindings.insert(*alias, env.get(*name)?);
273                }
274                UseTree::Name(name) => {
275                    bindings.insert(*name, env.get(*name)?);
276                }
277                UseTree::Glob => {
278                    trace!("TODO: Improve glob imports");
279                    if let Some((frame, name)) = env.pop_frame() {
280                        for (k, v) in &frame {
281                            bindings.insert(*k, v.clone());
282                        }
283                        env.push_frame(name, frame);
284                    }
285                }
286                other => {
287                    eprintln!("ERROR: Cannot use {other}");
288                }
289            }
290            Ok(())
291        }
292
293        let mut bindings = Bindings::new();
294        get_bindings(self, env, &mut bindings)?;
295
296        for (name, value) in bindings {
297            env.insert(name, value);
298        }
299
300        Ok(ConValue::Empty)
301    }
302}
303
304impl Interpret for Stmt {
305    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
306        let Self { span, kind, semi } = self;
307        let out = match kind {
308            StmtKind::Empty => Ok(ConValue::Empty),
309            StmtKind::Item(stmt) => stmt.interpret(env),
310            StmtKind::Expr(stmt) => stmt.interpret(env),
311        }
312        .map_err(|err| err.with_span(*span))?;
313        Ok(match semi {
314            Semi::Terminated => ConValue::Empty,
315            Semi::Unterminated => out,
316        })
317    }
318}
319
320impl Interpret for Expr {
321    #[inline]
322    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
323        let Self { span, kind } = self;
324        kind.interpret(env).map_err(|err| err.with_span(*span))
325    }
326}
327
328impl Interpret for ExprKind {
329    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
330        match self {
331            ExprKind::Empty => Ok(ConValue::Empty),
332            ExprKind::Closure(v) => v.interpret(env),
333            ExprKind::Quote(q) => q.interpret(env),
334            ExprKind::Let(v) => v.interpret(env),
335            ExprKind::Match(v) => v.interpret(env),
336            ExprKind::Assign(v) => v.interpret(env),
337            ExprKind::Modify(v) => v.interpret(env),
338            ExprKind::Binary(v) => v.interpret(env),
339            ExprKind::Unary(v) => v.interpret(env),
340            ExprKind::Cast(v) => v.interpret(env),
341            ExprKind::Member(v) => v.interpret(env),
342            ExprKind::Index(v) => v.interpret(env),
343            ExprKind::Structor(v) => v.interpret(env),
344            ExprKind::Path(v) => v.interpret(env),
345            ExprKind::Literal(v) => v.interpret(env),
346            ExprKind::Array(v) => v.interpret(env),
347            ExprKind::ArrayRep(v) => v.interpret(env),
348            ExprKind::AddrOf(v) => v.interpret(env),
349            ExprKind::Block(v) => v.interpret(env),
350            ExprKind::Group(v) => v.interpret(env),
351            ExprKind::Tuple(v) => v.interpret(env),
352            ExprKind::While(v) => v.interpret(env),
353            ExprKind::If(v) => v.interpret(env),
354            ExprKind::For(v) => v.interpret(env),
355            ExprKind::Break(v) => v.interpret(env),
356            ExprKind::Return(v) => v.interpret(env),
357            ExprKind::Continue => Err(Error::Continue()),
358        }
359    }
360}
361
362impl Interpret for Closure {
363    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
364        Ok(ConValue::Closure(
365            crate::closure::Closure::new(env, self).into(),
366        ))
367    }
368}
369
370impl Interpret for Quote {
371    fn interpret(&self, _env: &mut Environment) -> IResult<ConValue> {
372        // TODO: squoosh down into a ConValue?
373        Ok(ConValue::Quote(self.quote.as_ref().clone().into()))
374    }
375}
376
377impl Interpret for Let {
378    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
379        let Let { mutable: _, name, ty: _, init } = self;
380        match init.as_ref().map(|i| i.interpret(env)).transpose()? {
381            Some(value) => {
382                match pattern::substitution(env, name, value) {
383                    Ok(sub) => {
384                        for (name, value) in sub {
385                            env.insert(name, value);
386                        }
387                        return Ok(ConValue::Bool(true));
388                    }
389                    Err(_e) => trace!("{_e}"),
390                };
391            }
392            None => {
393                for name in pattern::variables(name) {
394                    env.insert(*name, ConValue::Empty);
395                }
396            }
397        }
398        Ok(ConValue::Bool(false))
399    }
400}
401
402impl Interpret for Match {
403    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
404        let Self { scrutinee, arms } = self;
405        let scrutinee = scrutinee.interpret(env)?;
406        for MatchArm(pat, expr) in arms {
407            if let Ok(substitution) = pattern::substitution(env, pat, scrutinee.clone()) {
408                let mut env = env.frame("match");
409                for (name, value) in substitution {
410                    env.insert(name, value);
411                }
412                return expr.interpret(&mut env);
413            }
414        }
415        Err(Error::MatchNonexhaustive())
416    }
417}
418
419pub(crate) mod assignment {
420    /// Pattern matching engine for assignment
421    use super::*;
422    use std::collections::HashMap;
423    type Namespace = HashMap<Sym, ConValue>;
424
425    pub(super) fn pat_assign(env: &mut Environment, pat: &Pattern, value: ConValue) -> IResult<()> {
426        for (name, value) in pattern::substitution(env, pat, value)
427            .map_err(|_| Error::PatFailed(pat.clone().into()))?
428        {
429            match env.get_mut(name)? {
430                &mut ConValue::Ref(id) => {
431                    *(env.get_id_mut(id).ok_or(Error::StackOverflow(id))?) = value;
432                }
433                other => *other = value,
434            }
435        }
436        Ok(())
437    }
438
439    pub(super) fn assign(env: &mut Environment, pat: &Expr, value: ConValue) -> IResult<()> {
440        if let Ok(pat) = Pattern::try_from(pat.clone()) {
441            return pat_assign(env, &pat, value);
442        }
443        match &pat.kind {
444            ExprKind::Member(member) => *addrof_member(env, member)? = value,
445            ExprKind::Index(index) => *addrof_index(env, index)? = value,
446            ExprKind::Path(path) => *addrof_path(env, &path.parts)? = value,
447            ExprKind::Unary(Unary { kind: UnaryKind::Deref, tail }) => match addrof(env, tail)? {
448                &mut ConValue::Ref(r) => *env.get_id_mut(r).ok_or(Error::StackOverflow(r))? = value,
449                _ => Err(Error::NotAssignable())?,
450            },
451            _ => Err(Error::NotAssignable())?,
452        }
453        Ok(())
454    }
455
456    pub(super) fn addrof<'e>(env: &'e mut Environment, pat: &Expr) -> IResult<&'e mut ConValue> {
457        match &pat.kind {
458            ExprKind::Path(path) => addrof_path(env, &path.parts),
459            ExprKind::Member(member) => addrof_member(env, member),
460            ExprKind::Index(index) => addrof_index(env, index),
461            ExprKind::Group(Group { expr }) => addrof(env, expr),
462            ExprKind::Unary(Unary { kind: UnaryKind::Deref, tail }) => match *addrof(env, tail)? {
463                ConValue::Ref(place) => env.get_id_mut(place).ok_or(Error::NotIndexable()),
464                _ => Err(Error::TypeError()),
465            },
466            _ => Err(Error::TypeError()),
467        }
468    }
469
470    pub fn addrof_path<'e>(
471        env: &'e mut Environment,
472        path: &[PathPart],
473    ) -> IResult<&'e mut ConValue> {
474        match path {
475            [PathPart::Ident(name)] => env.get_mut(*name),
476            [PathPart::Ident(name), rest @ ..] => match env.get_mut(*name)? {
477                ConValue::Module(env) => project_path_in_namespace(env, rest),
478                _ => Err(Error::NotIndexable()),
479            },
480            _ => Err(Error::NotAssignable()),
481        }
482    }
483
484    pub fn addrof_member<'e>(
485        env: &'e mut Environment,
486        member: &Member,
487    ) -> IResult<&'e mut ConValue> {
488        let Member { head, kind } = member;
489
490        let head = addrof(env, head)?;
491        project_memberkind(head, kind)
492    }
493
494    fn addrof_index<'e>(env: &'e mut Environment, index: &Index) -> IResult<&'e mut ConValue> {
495        let Index { head, indices } = index;
496        let indices = indices
497            .iter()
498            .map(|index| index.interpret(env))
499            .collect::<IResult<Vec<_>>>()?;
500
501        let mut head = addrof(env, head)?;
502        // match head {
503        //     ConValue::Slice(id, len) | ConValue::Array(id, len) => {
504
505        //     }
506        // }
507        for index in indices {
508            head = project_index(head, &index)?;
509        }
510        Ok(head)
511    }
512
513    /// Performs member-access "projection" from a ConValue to a particular element
514    pub fn project_memberkind<'v>(
515        value: &'v mut ConValue,
516        kind: &MemberKind,
517    ) -> IResult<&'v mut ConValue> {
518        match (value, kind) {
519            (ConValue::Struct(_name, s), MemberKind::Struct(id)) => {
520                s.get_mut(id).ok_or(Error::NotDefined(*id))
521            }
522            (ConValue::TupleStruct(_name, s), MemberKind::Tuple(Literal::Int(id))) => {
523                let len = s.len();
524                s.get_mut(*id as usize)
525                    .ok_or(Error::OobIndex(*id as _, len))
526            }
527            (ConValue::Tuple(t), MemberKind::Tuple(Literal::Int(id))) => {
528                let len = t.len();
529                t.get_mut(*id as usize)
530                    .ok_or(Error::OobIndex(*id as _, len))
531            }
532            _ => Err(Error::TypeError()),
533        }
534    }
535
536    /// Performs index "projection" from a ConValue to a particular element
537    pub fn project_index<'v>(
538        _value: &'v mut ConValue,
539        _index: &ConValue,
540    ) -> IResult<&'v mut ConValue> {
541        Err(Error::NotIndexable())
542    }
543
544    pub fn project_path_in_namespace<'e>(
545        env: &'e mut Namespace,
546        path: &[PathPart],
547    ) -> IResult<&'e mut ConValue> {
548        match path {
549            [] => Err(Error::NotAssignable()),
550            [PathPart::Ident(name)] => env.get_mut(name).ok_or(Error::NotDefined(*name)),
551            [PathPart::Ident(name), rest @ ..] => {
552                match env.get_mut(name).ok_or(Error::NotDefined(*name))? {
553                    ConValue::Module(env) => project_path_in_namespace(env, rest),
554                    _ => Err(Error::NotIndexable()),
555                }
556            }
557            [PathPart::SelfTy, ..] => todo!("calc_address for `Self`"),
558            [PathPart::SuperKw, ..] => todo!("calc_address for `super`"),
559        }
560    }
561}
562
563impl Interpret for Assign {
564    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
565        let Assign { parts } = self;
566        let (head, tail) = parts.borrow();
567        let init = tail.interpret(env)?;
568        // Resolve the head pattern
569        assignment::assign(env, head, init).map(|_| ConValue::Empty)
570    }
571}
572impl Interpret for Modify {
573    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
574        let Modify { kind: op, parts } = self;
575        let (head, tail) = parts.borrow();
576        // Get the initializer and the tail
577        let init = tail.interpret(env)?;
578        // Resolve the head pattern
579        let target = assignment::addrof(env, head)?;
580
581        match op {
582            ModifyKind::Add => target.add_assign(init),
583            ModifyKind::Sub => target.sub_assign(init),
584            ModifyKind::Mul => target.mul_assign(init),
585            ModifyKind::Div => target.div_assign(init),
586            ModifyKind::Rem => target.rem_assign(init),
587            ModifyKind::And => target.bitand_assign(init),
588            ModifyKind::Or => target.bitor_assign(init),
589            ModifyKind::Xor => target.bitxor_assign(init),
590            ModifyKind::Shl => target.shl_assign(init),
591            ModifyKind::Shr => target.shr_assign(init),
592        }?;
593        Ok(ConValue::Empty)
594    }
595}
596impl Interpret for Binary {
597    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
598        let Binary { kind, parts } = self;
599        let (head, tail) = parts.borrow();
600
601        let head = head.interpret(env)?;
602        match kind {
603            BinaryKind::LogAnd => {
604                return if head.truthy()? {
605                    tail.interpret(env)
606                } else {
607                    Ok(head)
608                }; // Short circuiting
609            }
610            BinaryKind::LogOr => {
611                return if !head.truthy()? {
612                    tail.interpret(env)
613                } else {
614                    Ok(head)
615                }; // Short circuiting
616            }
617            BinaryKind::LogXor => {
618                return Ok(ConValue::Bool(
619                    head.truthy()? ^ tail.interpret(env)?.truthy()?,
620                ));
621            }
622            _ => {}
623        }
624
625        let tail = tail.interpret(env)?;
626
627        #[allow(unused)]
628        let operator = match kind {
629            BinaryKind::Lt => "lt",
630            BinaryKind::LtEq => "lteq",
631            BinaryKind::Equal => "eq",
632            BinaryKind::NotEq => "neq",
633            BinaryKind::GtEq => "gteq",
634            BinaryKind::Gt => "gt",
635            BinaryKind::RangeExc => "range_exc",
636            BinaryKind::RangeInc => "range_inc",
637            BinaryKind::LogAnd => "log_and",
638            BinaryKind::LogOr => "log_or",
639            BinaryKind::LogXor => "log_xor",
640            BinaryKind::BitAnd => "bit_and",
641            BinaryKind::BitOr => "bit_or",
642            BinaryKind::BitXor => "bit_xor",
643            BinaryKind::Shl => "shl",
644            BinaryKind::Shr => "shr",
645            BinaryKind::Add => "add",
646            BinaryKind::Sub => "sub",
647            BinaryKind::Mul => "mul",
648            BinaryKind::Div => "div",
649            BinaryKind::Rem => "rem",
650            BinaryKind::Call => "call",
651        };
652
653        if let ConValue::Struct(name, _) | ConValue::TupleStruct(name, _) = head
654            && let Ok(ConValue::Module(m)) = env.get_mut(name)
655            && let Some(f) = m.get(&operator.into())
656        {
657            return f.clone().call(env, &[head, tail]);
658        }
659
660        if let Ok(ConValue::Module(m)) = env.get_mut(head.typename().into())
661            && let Some(f) = m.get(&operator.into())
662        {
663            return f.clone().call(env, &[head, tail]);
664        }
665
666        match kind {
667            BinaryKind::Lt => head.lt(&tail),
668            BinaryKind::LtEq => head.lt_eq(&tail),
669            BinaryKind::Equal => head.eq(&tail),
670            BinaryKind::NotEq => head.neq(&tail),
671            BinaryKind::GtEq => head.gt_eq(&tail),
672            BinaryKind::Gt => head.gt(&tail),
673            BinaryKind::RangeExc => env.call("RangeExc".into(), &[head, tail]),
674            BinaryKind::RangeInc => env.call("RangeInc".into(), &[head, tail]),
675            BinaryKind::BitAnd => head & tail,
676            BinaryKind::BitOr => head | tail,
677            BinaryKind::BitXor => head ^ tail,
678            BinaryKind::Shl => head << tail,
679            BinaryKind::Shr => head >> tail,
680            BinaryKind::Add => head + tail,
681            BinaryKind::Sub => head - tail,
682            BinaryKind::Mul => head * tail,
683            BinaryKind::Div => head / tail,
684            BinaryKind::Rem => head % tail,
685            BinaryKind::Call => match tail {
686                ConValue::Empty => head.call(env, &[]),
687                ConValue::Tuple(args) => head.call(env, &args),
688                _ => Err(Error::TypeError()),
689            },
690            _ => Ok(head),
691        }
692    }
693}
694
695impl Interpret for Unary {
696    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
697        let Unary { kind, tail } = self;
698        if *kind == UnaryKind::Loop {
699            loop {
700                match tail.interpret(env) {
701                    Err(Error { kind: ErrorKind::Break(value), .. }) => return Ok(value),
702                    Err(Error { kind: ErrorKind::Continue, .. }) => continue,
703                    e => e?,
704                };
705            }
706        }
707
708        let operator = match kind {
709            UnaryKind::Loop => unreachable!(),
710            UnaryKind::Deref => "deref",
711            UnaryKind::Neg => "neg",
712            UnaryKind::Not => "not",
713            UnaryKind::RangeExc => "RangeTo",
714            UnaryKind::RangeInc => "RangeToInc",
715            UnaryKind::At => "at",
716            UnaryKind::Tilde => "tilde",
717        };
718
719        let operand = tail.interpret(env)?;
720
721        if let ConValue::Struct(name, _) | ConValue::TupleStruct(name, _) = operand
722            && let Ok(ConValue::Module(m)) = env.get_mut(name)
723            && let Some(f) = m.get(&operator.into())
724        {
725            return f.clone().call(env, &[operand]);
726        }
727
728        if let Ok(ConValue::Module(m)) = env.get_mut(operand.typename().into())
729            && let Some(f) = m.get(&operator.into())
730        {
731            return f.clone().call(env, &[operand]);
732        }
733
734        env.call(operator.into(), &[operand])
735    }
736}
737
738fn cast(env: &Environment, value: ConValue, ty: Sym) -> IResult<ConValue> {
739    let value = match (value, ty.to_ref()) {
740        (value, "str") => return Ok(ConValue::Str(format!("{value}").into())),
741        (value, "String") => return Ok(ConValue::String(format!("{value}"))),
742        (ConValue::Empty, _) => 0,
743        (ConValue::Int(i), _) => i as _,
744        (ConValue::Bool(b), _) => b as _,
745        (ConValue::Char(c), _) => c as _,
746        (ConValue::Ref(v), _) => {
747            return cast(
748                env,
749                env.get_id(v).cloned().ok_or(Error::StackUnderflow())?,
750                ty,
751            );
752        }
753        (ConValue::Float(f), "f32" | "f64") => return Ok(ConValue::Float(f)),
754        (ConValue::Float(f), _) => f as _,
755        _ => Err(Error::TypeError())?,
756    };
757    Ok(match &*ty {
758        "u8" => ConValue::Int(value as u8 as _),
759        "i8" => ConValue::Int(value as i8 as _),
760        "u16" => ConValue::Int(value as u16 as _),
761        "i16" => ConValue::Int(value as i16 as _),
762        "u32" => ConValue::Int(value as u32 as _),
763        "i32" => ConValue::Int(value as i32 as _),
764        "u64" => ConValue::Int(value),
765        "i64" => ConValue::Int(value),
766        "f32" => ConValue::Float(value as f32 as _),
767        "f64" => ConValue::Float(value as f64 as _),
768        "char" => ConValue::Char(char::from_u32(value as _).unwrap_or('\u{fffd}')),
769        "bool" => ConValue::Bool(value != 0),
770        _ => Err(Error::NotDefined(ty))?,
771    })
772}
773
774impl Interpret for Cast {
775    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
776        let Cast { head, ty } = self;
777        let value = head.interpret(env)?;
778
779        if let TyKind::Tuple(TyTuple { types }) = &ty.kind
780            && types.as_slice().is_empty()
781        {
782            return Ok(ConValue::Empty);
783        }
784        let TyKind::Path(Path { absolute: false, parts }) = &ty.kind else {
785            Err(Error::TypeError())?
786        };
787        match parts.as_slice() {
788            [PathPart::Ident(ty)] => cast(env, value, *ty),
789            _ => Err(Error::TypeError()),
790        }
791    }
792}
793
794impl Interpret for Member {
795    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
796        let Member { head, kind } = self;
797        // Attempt member access projection (fast path)
798        if let Ok(member) = assignment::addrof_member(env, self) {
799            return Ok(member.clone());
800        }
801        let mut values = vec![];
802
803        // Evaluate if this can be Self'd
804        let addr = match (&head.kind, kind) {
805            (ExprKind::Path(p), MemberKind::Call(..)) => {
806                p.as_sym()
807                    .and_then(|name| Some(ConValue::Ref(env.id_of(name).ok()?))) // "borrow" it
808            }
809            _ => None,
810        };
811
812        let mut value = head.interpret(env)?;
813
814        // Perform alternate member access
815        match (&value, &kind) {
816            (ConValue::Struct(_name, memb), MemberKind::Call(name, args))
817                if memb.contains_key(name) =>
818            {
819                let f = memb.get(name).cloned().expect("function exists");
820                values.push(addr.unwrap_or(value));
821                for arg in &args.exprs {
822                    values.push(arg.interpret(env)?);
823                }
824                f.call(env, &values)
825            }
826            (_, MemberKind::Call(name, args)) => {
827                values.push(addr.unwrap_or(value));
828                for arg in &args.exprs {
829                    values.push(arg.interpret(env)?);
830                }
831                env.call(*name, &values)
832            }
833            (_, kind) => assignment::project_memberkind(&mut value, kind).cloned(),
834        }
835    }
836}
837impl Interpret for Index {
838    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
839        let Self { head, indices } = self;
840        let mut head = head.interpret(env)?;
841        for index in indices {
842            head = head.index(&index.interpret(env)?, env)?;
843        }
844        Ok(head)
845    }
846}
847impl Interpret for Structor {
848    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
849        let Self { to: Path { absolute: _, parts }, init } = self;
850        use std::collections::HashMap;
851
852        // Look up struct/enum-struct definition
853        // use that definition to place the struct parts
854
855        let name = match parts.last() {
856            Some(PathPart::Ident(name)) => *name,
857            Some(PathPart::SelfTy) => "Self".into(),
858            Some(PathPart::SuperKw) => "super".into(),
859            None => "".into(),
860        };
861
862        let mut map = HashMap::new();
863        for Fielder { name, init } in init {
864            let value = match init {
865                Some(init) => init.interpret(env)?,
866                None => env.get(*name)?,
867            };
868            map.insert(*name, value);
869        }
870        Ok(ConValue::Struct(name, Box::new(map)))
871    }
872}
873
874impl Interpret for Path {
875    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
876        let Self { absolute: _, parts } = self;
877
878        assignment::addrof_path(env, parts).cloned()
879    }
880}
881impl Interpret for Literal {
882    fn interpret(&self, _env: &mut Environment) -> IResult<ConValue> {
883        Ok(match self {
884            Literal::String(value) => ConValue::from(value.as_str()),
885            Literal::Char(value) => ConValue::Char(*value),
886            Literal::Bool(value) => ConValue::Bool(*value),
887            Literal::Float(value) => ConValue::Float(f64::from_bits(*value)),
888            Literal::Int(value) => ConValue::Int(*value as _),
889        })
890    }
891}
892impl Interpret for Array {
893    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
894        let Self { values } = self;
895        let mut out = vec![];
896        for expr in values {
897            out.push(expr.interpret(env)?)
898        }
899        Ok(ConValue::Array(out.into()))
900    }
901}
902impl Interpret for ArrayRep {
903    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
904        let Self { value, repeat } = self;
905        let value = value.interpret(env)?;
906        let ConValue::Int(repeat) = repeat.interpret(env)? else {
907            Err(Error::TypeError())?
908        };
909        if repeat < 0 {
910            // TODO: a special error just for you
911            Err(Error::NotIndexable())?
912        }
913
914        Ok(ConValue::Array(vec![value; repeat as usize].into()))
915    }
916}
917impl Interpret for AddrOf {
918    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
919        let Self { mutable: _, expr } = self;
920        match &expr.kind {
921            ExprKind::Index(_) => todo!("AddrOf array index"),
922            ExprKind::Path(Path { parts, .. }) => match parts.as_slice() {
923                [PathPart::Ident(name)] => Ok(ConValue::Ref(env.id_of(*name)?)),
924                _ => todo!("Path traversal in AddrOf(\"{self}\")"),
925            },
926            _ => {
927                let value = expr.interpret(env)?;
928                let temp = env.stack_alloc(value)?;
929                Ok(ConValue::Ref(temp))
930            }
931        }
932    }
933}
934impl Interpret for Block {
935    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
936        let Self { stmts } = self;
937        let mut env = env.frame("block");
938        let mut out = ConValue::Empty;
939        for stmt in stmts {
940            out = stmt.interpret(&mut env)?;
941        }
942        Ok(out)
943    }
944}
945impl Interpret for Group {
946    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
947        let Self { expr } = self;
948        expr.interpret(env)
949    }
950}
951impl Interpret for Tuple {
952    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
953        let Self { exprs } = self;
954        Ok(ConValue::Tuple(
955            exprs
956                .iter()
957                .try_fold(vec![], |mut out, element| {
958                    out.push(element.interpret(env)?);
959                    Ok(out)
960                })?
961                .into(),
962        ))
963    }
964}
965impl Interpret for While {
966    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
967        let Self { cond, pass, fail } = self;
968        loop {
969            if cond.interpret(env)?.truthy()? {
970                match pass.interpret(env) {
971                    Err(Error { kind: ErrorKind::Break(value), .. }) => break Ok(value),
972                    Err(Error { kind: ErrorKind::Continue, .. }) => continue,
973                    e => e?,
974                };
975            } else {
976                break fail.interpret(env);
977            }
978        }
979    }
980}
981impl Interpret for If {
982    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
983        let Self { cond, pass, fail } = self;
984        if cond.interpret(env)?.truthy()? {
985            pass.interpret(env)
986        } else {
987            fail.interpret(env)
988        }
989    }
990}
991impl Interpret for For {
992    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
993        let Self { bind, cond, pass, fail } = self;
994        let cond = cond.interpret(env)?;
995        // TODO: A better iterator model
996        let mut bounds: Box<dyn Iterator<Item = ConValue>> = match &cond {
997            ConValue::TupleStruct(name, values) => match name.to_ref() {
998                "RangeExc" => match values.as_ref().as_ref() {
999                    &[ConValue::Int(from), ConValue::Int(to)] => {
1000                        Box::new((from..to).map(ConValue::Int))
1001                    }
1002                    _ => Err(Error::NotIterable())?,
1003                },
1004                "RangeInc" => match values.as_ref().as_ref() {
1005                    &[ConValue::Int(from), ConValue::Int(to)] => {
1006                        Box::new((from..=to).map(ConValue::Int))
1007                    }
1008                    _ => Err(Error::NotIterable())?,
1009                },
1010                _ => Err(Error::NotIterable())?,
1011            },
1012            ConValue::Array(a) => Box::new(a.iter().cloned()),
1013            &ConValue::Slice(head, len) => Box::new((head..head + len).map(ConValue::Ref)),
1014            // In the production compiler this may be fully unrolled
1015            ConValue::Tuple(t) => Box::new(t.iter().cloned()),
1016            ConValue::Str(s) => Box::new(s.chars().map(ConValue::Char)),
1017            _ => Err(Error::TypeError())?,
1018        };
1019        loop {
1020            let mut env = env.frame("loop variable");
1021            if let Some(value) = bounds.next() {
1022                for (name, value) in pattern::substitution(&env, bind, value)? {
1023                    env.insert(name, value);
1024                }
1025                match pass.interpret(&mut env) {
1026                    Err(Error { kind: ErrorKind::Break(value), .. }) => break Ok(value),
1027                    Err(Error { kind: ErrorKind::Continue, .. }) => continue,
1028                    e => e?,
1029                };
1030            } else {
1031                break fail.interpret(&mut env);
1032            }
1033        }
1034    }
1035}
1036impl Interpret for Else {
1037    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
1038        let Self { body } = self;
1039        match body {
1040            Some(body) => body.interpret(env),
1041            None => Ok(ConValue::Empty),
1042        }
1043    }
1044}
1045impl Interpret for Return {
1046    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
1047        let Self { body } = self;
1048        Err(Error::Return(
1049            body.as_ref()
1050                .map(|body| body.interpret(env))
1051                .unwrap_or(Ok(ConValue::Empty))?,
1052        ))
1053    }
1054}
1055impl Interpret for Break {
1056    fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
1057        let Self { body } = self;
1058        Err(Error::Break(
1059            body.as_ref()
1060                .map(|body| body.interpret(env))
1061                .unwrap_or(Ok(ConValue::Empty))?,
1062        ))
1063    }
1064}