New plans for macros
About to move them completely to stdlib
This commit is contained in:
@@ -1,210 +1,124 @@
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{Display, Write};
|
||||
use std::ops::Range;
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
use orchid_api::tree::{Item, ItemKind, Macro, Member, MemberKind, Module, Paren, Token, TokenTree, TreeId, TreeTicket};
|
||||
use orchid_base::error::OwnedError;
|
||||
use orchid_base::error::OrcRes;
|
||||
use orchid_base::interner::{deintern, Tok};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::tokens::{OwnedPh, PARENS};
|
||||
use orchid_base::parse::{Comment, CompName};
|
||||
use orchid_base::tree::{ttv_from_api, TokTree, Token};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::api;
|
||||
use crate::expr::RtExpr;
|
||||
use crate::extension::{AtomHand, System};
|
||||
use crate::results::OwnedResult;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OwnedTokTree {
|
||||
pub tok: OwnedTok,
|
||||
pub range: Range<u32>,
|
||||
}
|
||||
impl OwnedTokTree {
|
||||
pub fn from_api<E>(
|
||||
tt: &TokenTree,
|
||||
sys: &System,
|
||||
do_slot: &mut impl FnMut(&TreeTicket, Range<u32>) -> Result<Self, E>,
|
||||
) -> Result<Self, E> {
|
||||
let tok = match &tt.token {
|
||||
Token::Atom(a) => OwnedTok::Atom(AtomHand::from_api(a.clone().associate(sys.id()))),
|
||||
Token::BR => OwnedTok::BR,
|
||||
Token::NS => OwnedTok::NS,
|
||||
Token::Bottom(e) => OwnedTok::Bottom(e.iter().map(OwnedError::from_api).collect_vec()),
|
||||
Token::Lambda(arg) => OwnedTok::Lambda(Self::v_from_api(arg, sys, do_slot)?),
|
||||
Token::Name(name) => OwnedTok::Name(deintern(*name)),
|
||||
Token::Ph(ph) => OwnedTok::Ph(OwnedPh::from_api(ph.clone())),
|
||||
Token::S(par, b) => OwnedTok::S(par.clone(), Self::v_from_api(b, sys, do_slot)?),
|
||||
Token::Slot(id) => return do_slot(id, tt.range.clone()),
|
||||
};
|
||||
Ok(Self { range: tt.range.clone(), tok })
|
||||
}
|
||||
|
||||
pub fn v_from_api<E>(
|
||||
tokv: impl IntoIterator<Item: Borrow<TokenTree>>,
|
||||
sys: &System,
|
||||
do_slot: &mut impl FnMut(&TreeTicket, Range<u32>) -> Result<Self, E>,
|
||||
) -> Result<Vec<Self>, E> {
|
||||
tokv.into_iter().map(|t| Self::from_api(t.borrow(), sys, do_slot)).collect()
|
||||
}
|
||||
}
|
||||
impl Display for OwnedTokTree {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.tok) }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OwnedTok {
|
||||
Comment(String),
|
||||
Lambda(Vec<OwnedTokTree>),
|
||||
Name(Tok<String>),
|
||||
NS,
|
||||
BR,
|
||||
S(Paren, Vec<OwnedTokTree>),
|
||||
Atom(AtomHand),
|
||||
Ph(OwnedPh),
|
||||
Bottom(Vec<OwnedError>),
|
||||
}
|
||||
impl Display for OwnedTok {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
thread_local! {
|
||||
static PAREN_LEVEL: RefCell<usize> = 0.into();
|
||||
}
|
||||
fn get_indent() -> usize { PAREN_LEVEL.with_borrow(|t| *t) }
|
||||
fn with_indent<T>(f: impl FnOnce() -> T) -> T {
|
||||
PAREN_LEVEL.with_borrow_mut(|t| *t += 1);
|
||||
let r = f();
|
||||
PAREN_LEVEL.with_borrow_mut(|t| *t -= 1);
|
||||
r
|
||||
}
|
||||
match self {
|
||||
Self::Atom(ah) => f.write_str(&indent(&ah.print(), get_indent(), false)),
|
||||
Self::BR => write!(f, "\n{}", " ".repeat(get_indent())),
|
||||
Self::Bottom(err) => write!(f, "Botttom({})",
|
||||
err.iter().map(|e| format!("{}: {}", e.description, e.message)).join(", ")
|
||||
),
|
||||
Self::Comment(c) => write!(f, "--[{c}]--"),
|
||||
Self::Lambda(arg) => with_indent(|| write!(f, "\\ {} .", fmt_tt_v(arg))),
|
||||
Self::NS => f.write_str("::"),
|
||||
Self::Name(n) => f.write_str(n),
|
||||
Self::Ph(ph) => write!(f, "{ph}"),
|
||||
Self::S(p, b) => {
|
||||
let (lp, rp, _) = PARENS.iter().find(|(_, _, par)| par == p).unwrap();
|
||||
f.write_char(*lp)?;
|
||||
with_indent(|| f.write_str(&fmt_tt_v(b)))?;
|
||||
f.write_char(*rp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fmt_tt_v<'a>(ttv: impl IntoIterator<Item = &'a OwnedTokTree>) -> String {
|
||||
ttv.into_iter().join(" ")
|
||||
}
|
||||
|
||||
pub fn indent(s: &str, lvl: usize, first: bool) -> String {
|
||||
if first {
|
||||
s.replace("\n", &("\n".to_string() + &" ".repeat(lvl)))
|
||||
} else if let Some((fst, rest)) = s.split_once('\n') {
|
||||
fst.to_string() + "\n" + &indent(rest, lvl, true)
|
||||
} else {
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
pub type ParsTokTree = TokTree<'static, AtomHand, Never>;
|
||||
pub type ParsTok = Token<'static, AtomHand, Never>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OwnedItem {
|
||||
pub struct Item {
|
||||
pub pos: Pos,
|
||||
pub kind: OwnedItemKind,
|
||||
pub comments: Vec<Comment>,
|
||||
pub kind: ItemKind,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OwnedItemKind {
|
||||
Raw(Vec<OwnedTokTree>),
|
||||
Member(OwnedMember),
|
||||
Rule(OwnedMacro),
|
||||
pub enum ItemKind {
|
||||
Raw(Vec<ParsTokTree>),
|
||||
Member(Member),
|
||||
Export(Tok<String>),
|
||||
Rule(Macro),
|
||||
Import(CompName),
|
||||
}
|
||||
|
||||
fn slot_panic(_: &TreeTicket, _: Range<u32>) -> Result<OwnedTokTree, Never> {
|
||||
panic!("No slots allowed at item stage")
|
||||
}
|
||||
|
||||
impl OwnedItem {
|
||||
pub fn from_api(tree: Item, sys: &System) -> Self {
|
||||
impl Item {
|
||||
pub fn from_api(tree: api::Item, sys: &System) -> Self {
|
||||
let kind = match tree.kind {
|
||||
ItemKind::Raw(tokv) =>
|
||||
OwnedItemKind::Raw(OwnedTokTree::v_from_api::<Never>(tokv, sys, &mut slot_panic).unwrap()),
|
||||
ItemKind::Member(m) => OwnedItemKind::Member(OwnedMember::from_api(m, sys)),
|
||||
ItemKind::Rule(r) => OwnedItemKind::Rule(OwnedMacro::from_api(r, sys)),
|
||||
api::ItemKind::Raw(tokv) => ItemKind::Raw(ttv_from_api(tokv, &mut ())),
|
||||
api::ItemKind::Member(m) => ItemKind::Member(Member::from_api(m, sys)),
|
||||
api::ItemKind::Rule(r) => ItemKind::Rule(Macro::from_api(r)),
|
||||
api::ItemKind::Import(i) => ItemKind::Import(CompName::from_api(i)),
|
||||
api::ItemKind::Export(e) => ItemKind::Export(deintern(e)),
|
||||
};
|
||||
Self { pos: Pos::from_api(&tree.location), kind }
|
||||
let comments = tree
|
||||
.comments
|
||||
.into_iter()
|
||||
.map(|(text, l)| Comment { text, pos: Pos::from_api(&l) })
|
||||
.collect_vec();
|
||||
Self { pos: Pos::from_api(&tree.location), comments, kind }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OwnedMember {
|
||||
pub public: bool,
|
||||
pub struct Member {
|
||||
pub exported: bool,
|
||||
pub name: Tok<String>,
|
||||
pub kind: OnceLock<OMemKind>,
|
||||
pub kind: OnceLock<MemberKind>,
|
||||
pub lazy: Mutex<Option<LazyMemberHandle>>,
|
||||
}
|
||||
impl OwnedMember {
|
||||
pub fn from_api(Member{ public, name, kind }: Member, sys: &System) -> Self {
|
||||
impl Member {
|
||||
pub fn from_api(api::Member { exported: public, name, kind }: api::Member, sys: &System) -> Self {
|
||||
let (kind, lazy) = match kind {
|
||||
MemberKind::Const(c) => (OnceLock::from(OMemKind::Const(RtExpr::from_api(c, sys))), None),
|
||||
MemberKind::Module(m) => (OnceLock::from(OMemKind::Mod(OwnedModule::from_api(m, sys))), None),
|
||||
MemberKind::Lazy(id) => (OnceLock::new(), Some(LazyMemberHandle(id, sys.clone())))
|
||||
api::MemberKind::Const(c) =>
|
||||
(OnceLock::from(MemberKind::PreCnst(RtExpr::from_api(c, sys))), None),
|
||||
api::MemberKind::Module(m) =>
|
||||
(OnceLock::from(MemberKind::Mod(Module::from_api(m, sys))), None),
|
||||
api::MemberKind::Lazy(id) => (OnceLock::new(), Some(LazyMemberHandle(id, sys.clone()))),
|
||||
};
|
||||
OwnedMember { public, name: deintern(name), kind, lazy: Mutex::new(lazy) }
|
||||
Member { exported: public, name: deintern(name), kind, lazy: Mutex::new(lazy) }
|
||||
}
|
||||
pub fn new(public: bool, name: Tok<String>, kind: MemberKind) -> Self {
|
||||
Member { exported: public, name, kind: OnceLock::from(kind), lazy: Mutex::default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OMemKind {
|
||||
Const(RtExpr),
|
||||
Mod(OwnedModule),
|
||||
pub enum MemberKind {
|
||||
Const(Vec<ParsTokTree>),
|
||||
PreCnst(RtExpr),
|
||||
Mod(Module),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OwnedModule {
|
||||
pub struct Module {
|
||||
pub imports: Vec<Sym>,
|
||||
pub items: Vec<OwnedItem>,
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
impl OwnedModule {
|
||||
pub fn from_api(m: Module, sys: &System) -> Self {
|
||||
impl Module {
|
||||
pub fn from_api(m: api::Module, sys: &System) -> Self {
|
||||
Self {
|
||||
imports: m.imports.into_iter().map(|m| Sym::from_tok(deintern(m)).unwrap()).collect_vec(),
|
||||
items: m.items.into_iter().map(|i| OwnedItem::from_api(i, sys)).collect_vec(),
|
||||
items: m.items.into_iter().map(|i| Item::from_api(i, sys)).collect_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OwnedMacro {
|
||||
pub struct Macro {
|
||||
pub priority: NotNan<f64>,
|
||||
pub pattern: Vec<OwnedTokTree>,
|
||||
pub template: Vec<OwnedTokTree>,
|
||||
pub pattern: Vec<ParsTokTree>,
|
||||
pub template: Vec<ParsTokTree>,
|
||||
}
|
||||
impl OwnedMacro {
|
||||
pub fn from_api(m: Macro, sys: &System) -> Self {
|
||||
impl Macro {
|
||||
pub fn from_api(m: api::Macro) -> Self {
|
||||
Self {
|
||||
priority: m.priority,
|
||||
pattern: OwnedTokTree::v_from_api(m.pattern, sys, &mut slot_panic).unwrap(),
|
||||
template: OwnedTokTree::v_from_api(m.template, sys, &mut slot_panic).unwrap(),
|
||||
pattern: ttv_from_api(m.pattern, &mut ()),
|
||||
template: ttv_from_api(m.template, &mut ()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LazyMemberHandle(TreeId, System);
|
||||
pub struct LazyMemberHandle(api::TreeId, System);
|
||||
impl LazyMemberHandle {
|
||||
pub fn run(self) -> OwnedResult<OMemKind> {
|
||||
pub fn run(self) -> OrcRes<MemberKind> {
|
||||
match self.1.get_tree(self.0) {
|
||||
MemberKind::Const(c) => Ok(OMemKind::Const(RtExpr::from_api(c, &self.1))),
|
||||
MemberKind::Module(m) => Ok(OMemKind::Mod(OwnedModule::from_api(m, &self.1))),
|
||||
MemberKind::Lazy(id) => Self(id, self.1).run()
|
||||
api::MemberKind::Const(c) => Ok(MemberKind::PreCnst(RtExpr::from_api(c, &self.1))),
|
||||
api::MemberKind::Module(m) => Ok(MemberKind::Mod(Module::from_api(m, &self.1))),
|
||||
api::MemberKind::Lazy(id) => Self(id, self.1).run(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user