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