Macro processing factored into Orchid functions

This commit is contained in:
2025-01-08 01:34:40 +00:00
parent e780969c6c
commit 7cdfe7e3c4
36 changed files with 631 additions and 289 deletions

View File

@@ -1,20 +1,36 @@
use std::sync::Arc;
#![allow(unused)]
use std::any::Any;
use hashbrown::HashMap;
use orchid_api::PhKind;
use orchid_base::tree::Ph;
use orchid_base::{interner::Tok, join::join_maps};
use orchid_base::interner::Tok;
use orchid_base::join::join_maps;
use orchid_base::location::Pos;
use crate::macros::{MacTok, MacTree};
use orchid_base::match_mapping;
use orchid_base::name::Sym;
use crate::macros::MacTree;
enum StackAction {
Return(Box<dyn Any>),
Call {
target: Box<dyn FnOnce(Box<dyn Any>) -> StackAction>,
param: Box<dyn Any>,
tail: Box<dyn FnOnce(Box<dyn Any>) -> StackAction>
}
}
struct Trampoline {
stack: Vec<Box<dyn FnOnce(Box<dyn Any>) -> StackAction>>
}
#[derive(Clone, Copy, Debug)]
pub enum StateEntry<'a> {
Vec(&'a [MacTree]),
Scalar(&'a MacTree),
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct MatchState<'a> {
placeholders: HashMap<Tok<String>, StateEntry<'a>>,
name_posv: HashMap<Sym, Vec<Pos>>,
@@ -26,9 +42,7 @@ impl<'a> MatchState<'a> {
pub fn combine(self, s: Self) -> Self {
Self {
placeholders: self.placeholders.into_iter().chain(s.placeholders).collect(),
name_posv: join_maps(self.name_posv, s.name_posv, |_, l, r| {
l.into_iter().chain(r).collect()
}),
name_posv: join_maps(self.name_posv, s.name_posv, |_, l, r| l.into_iter().chain(r).collect()),
}
}
pub fn ph_len(&self, key: &Tok<String>) -> Option<usize> {
@@ -40,45 +54,40 @@ impl<'a> MatchState<'a> {
pub fn from_name(name: Sym, location: Pos) -> Self {
Self { name_posv: HashMap::from([(name, vec![location])]), placeholders: HashMap::new() }
}
pub fn remove(&mut self, name: Tok<String>) -> Option<StateEntry<'a>> {
self.placeholders.remove(&name)
}
pub fn mk_owned(self) -> OwnedState {
OwnedState {
placeholders: (self.placeholders.into_iter())
.map(|(k, v)| {
(
k.clone(),
match_mapping!(v, StateEntry => OwnedEntry {
Scalar(tree.clone()),
Vec(v.to_vec()),
}),
)
})
.collect(),
name_posv: self.name_posv,
}
}
}
impl Default for MatchState<'static> {
fn default() -> Self { Self { name_posv: HashMap::new(), placeholders: HashMap::new() } }
}
#[must_use]
pub fn apply_exprv(template: &[MacTree], state: &MatchState) -> Vec<MacTree> {
template.iter().map(|e| apply_expr(e, state)).flat_map(Vec::into_iter).collect()
#[derive(Clone, Debug)]
pub enum OwnedEntry {
Vec(Vec<MacTree>),
Scalar(MacTree),
}
#[must_use]
pub fn apply_expr(template: &MacTree, state: &MatchState) -> Vec<MacTree> {
let MacTree { pos, tok } = template;
match &**tok {
MacTok::Name(n) => match state.name_posv.get(n) {
None => vec![template.clone()],
Some(locs) => vec![MacTree { tok: tok.clone(), pos: locs[0].clone() }],
},
MacTok::Atom(_) => vec![template.clone()],
MacTok::S(c, body) => vec![MacTree {
pos: pos.clone(), tok: Arc::new(MacTok::S(*c, apply_exprv(body.as_slice(), state))),
}],
MacTok::Ph(Ph { name, kind }) => {
let Some(value) = state.placeholders.get(name) else {
panic!("Placeholder does not have a value in state")
};
match (kind, value) {
(PhKind::Scalar, StateEntry::Scalar(item)) => vec![(*item).clone()],
(PhKind::Vector { .. }, StateEntry::Vec(chunk)) => chunk.to_vec(),
_ => panic!("Type mismatch between template and state"),
}
},
MacTok::Lambda(arg, body) => vec![MacTree {
pos: pos.clone(),
tok: Arc::new(MacTok::Lambda(
apply_exprv(arg, state),
apply_exprv(&body[..], state),
)),
}],
MacTok::Slot(_) | MacTok::Ref(_) => panic!("Extension-only variants"),
}
pub struct OwnedState {
placeholders: HashMap<Tok<String>, OwnedEntry>,
name_posv: HashMap<Sym, Vec<Pos>>,
}
impl OwnedState {
pub fn get(&self, key: &Tok<String>) -> Option<&OwnedEntry> { self.placeholders.get(key) }
pub fn positions(&self, name: &Sym) -> &[Pos] { self.name_posv.get(name).map_or(&[], |v| &v[..]) }
}