Macro system done in theory

too afraid to begin debugging, resting for a moment
This commit is contained in:
2025-09-03 16:05:26 +02:00
parent 051b5e666f
commit 7031f3a7d8
51 changed files with 1463 additions and 458 deletions

View File

@@ -1,7 +1,7 @@
use std::ops::RangeInclusive;
use orchid_base::error::OrcRes;
use orchid_base::number::{num_to_err, parse_num};
use orchid_base::number::{num_to_errv, parse_num};
use orchid_extension::atom::ToAtom;
use orchid_extension::lexer::{LexContext, Lexer};
use orchid_extension::tree::{GenTokTree, x_tok};
@@ -17,8 +17,8 @@ impl Lexer for NumLexer {
let (chars, tail) = all.split_at(ends_at.unwrap_or(all.len()));
let fac = match parse_num(chars) {
Ok(numeric) => Num(numeric).to_atom_factory(),
Err(e) => return Err(num_to_err(e, ctx.pos(all), &ctx.src, ctx.ctx.i()).await.into()),
Err(e) => return Err(num_to_errv(e, ctx.pos(all), ctx.src(), ctx.ctx.i()).await),
};
Ok((tail, x_tok(fac).at(ctx.pos_lt(chars.len(), tail))))
Ok((tail, x_tok(fac).await.at(ctx.pos_lt(chars.len(), tail))))
}
}

View File

@@ -49,7 +49,7 @@ impl OwnedAtom for StrAtom {
async fn serialize(&self, _: SysCtx, sink: Pin<&mut (impl Write + ?Sized)>) -> Self::Refs {
self.deref().encode(sink).await
}
async fn print<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
async fn print_atom<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
format!("{:?}", &*self.0).into()
}
async fn deserialize(mut ctx: impl DeserializeCtx, _: Self::Refs) -> Self {
@@ -69,7 +69,7 @@ impl From<Tok<String>> for IntStrAtom {
impl OwnedAtom for IntStrAtom {
type Refs = ();
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(self.0.to_api()) }
async fn print<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
async fn print_atom<'a>(&'a self, _: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
format!("{:?}i", *self.0).into()
}
async fn serialize(&self, _: SysCtx, write: Pin<&mut (impl Write + ?Sized)>) {
@@ -108,7 +108,7 @@ impl TryFromExpr for OrcString {
}
let ctx = expr.ctx();
match TypAtom::<IntStrAtom>::try_from_expr(expr).await {
Ok(t) => Ok(OrcString { ctx: t.data.ctx(), kind: OrcStringKind::Int(t) }),
Ok(t) => Ok(OrcString { ctx: t.untyped.ctx().clone(), kind: OrcStringKind::Int(t) }),
Err(e) => Err(mk_errv(ctx.i().i("A string was expected").await, "", e.pos_iter())),
}
}

View File

@@ -1,11 +1,13 @@
use itertools::Itertools;
use orchid_base::error::{OrcErr, OrcRes, mk_err, mk_errv};
use orchid_base::error::{OrcErr, OrcErrv, OrcRes, mk_errv};
use orchid_base::interner::Interner;
use orchid_base::location::SrcRange;
use orchid_base::name::Sym;
use orchid_base::parse::ParseCtx;
use orchid_base::sym;
use orchid_base::tree::wrap_tokv;
use orchid_extension::lexer::{LexContext, Lexer, err_not_applicable};
use orchid_extension::parser::p_tree2gen;
use orchid_extension::tree::{GenTokTree, ref_tok, x_tok};
use super::str_atom::IntStrAtom;
@@ -32,16 +34,16 @@ struct StringError {
impl StringError {
/// Convert into project error for reporting
pub async fn into_proj(self, path: &Sym, pos: u32, i: &Interner) -> OrcErr {
pub async fn into_proj(self, path: &Sym, pos: u32, i: &Interner) -> OrcErrv {
let start = pos + self.pos;
mk_err(
mk_errv(
i.i("Failed to parse string").await,
match self.kind {
StringErrorKind::NotHex => "Expected a hex digit",
StringErrorKind::BadCodePoint => "The specified number is not a Unicode code point",
StringErrorKind::BadEscSeq => "Unrecognized escape sequence",
},
[SrcRange::new(start..start + 1, path).pos().into()],
[SrcRange::new(start..start + 1, path).pos()],
)
}
}
@@ -97,7 +99,7 @@ impl Lexer for StringLexer {
const CHAR_FILTER: &'static [std::ops::RangeInclusive<char>] = &['"'..='"', '`'..='`'];
async fn lex<'a>(all: &'a str, ctx: &'a LexContext<'a>) -> OrcRes<(&'a str, GenTokTree)> {
let Some(mut tail) = all.strip_prefix('"') else {
return Err(err_not_applicable(ctx.ctx.i()).await.into());
return Err(err_not_applicable(ctx.ctx.i()).await);
};
let mut ret = None;
let mut cur = String::new();
@@ -110,15 +112,17 @@ impl Lexer for StringLexer {
) -> GenTokTree {
let str_val_res = parse_string(&str.split_off(0));
if let Err(e) = &str_val_res {
err.push(e.clone().into_proj(&ctx.src, ctx.pos(tail) - str.len() as u32, ctx.i()).await);
err.extend(e.clone().into_proj(ctx.src(), ctx.pos(tail) - str.len() as u32, ctx.i()).await);
}
let str_val = str_val_res.unwrap_or_default();
x_tok(IntStrAtom::from(ctx.i().i(&*str_val).await)).at(ctx.pos_lt(str.len() as u32, tail))
as GenTokTree
x_tok(IntStrAtom::from(ctx.i().i(&*str_val).await))
.await
.at(ctx.pos_lt(str.len() as u32, tail)) as GenTokTree
}
let add_frag = |prev: Option<GenTokTree>, new: GenTokTree| async {
let Some(prev) = prev else { return new };
let concat_fn = ref_tok(sym!(std::string::concat; ctx.i()).await)
.await
.at(SrcRange::zw(prev.sr.path(), prev.sr.start()));
wrap_tokv([concat_fn, prev, new])
};
@@ -129,7 +133,7 @@ impl Lexer for StringLexer {
ret = Some(add_frag(ret, str_to_gen(&mut cur, tail, &mut errors, ctx).await).await);
let (new_tail, tree) = ctx.recurse(rest).await?;
tail = new_tail;
ret = Some(add_frag(ret, tree).await);
ret = Some(add_frag(ret, p_tree2gen(tree)).await);
} else if tail.starts_with('\\') {
// parse_string will deal with it, we just have to skip the next char
tail = &tail[2..];
@@ -143,7 +147,7 @@ impl Lexer for StringLexer {
return Err(mk_errv(
ctx.i().i("No string end").await,
"String never terminated with \"",
[SrcRange::new(range.clone(), &ctx.src)],
[SrcRange::new(range.clone(), ctx.src())],
));
}
}