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

@@ -6,7 +6,7 @@ macro_rules! clone {
$body
}
);
($($n:ident),+) => {
$( let $n = $n.clone(); )+
($($n:ident $($mut:ident)?),+) => {
$( let $($mut)? $n = $n.clone(); )+
}
}

View File

@@ -71,9 +71,8 @@ impl OrcErr {
}
}
}
impl Eq for OrcErr {}
impl PartialEq for OrcErr {
fn eq(&self, other: &Self) -> bool { self.description == other.description }
impl PartialEq<Tok<String>> for OrcErr {
fn eq(&self, other: &Tok<String>) -> bool { self.description == *other }
}
impl From<OrcErr> for Vec<OrcErr> {
fn from(value: OrcErr) -> Self { vec![value] }
@@ -192,16 +191,8 @@ macro_rules! join_ok {
(@VALUES) => { Ok(()) };
}
pub fn mk_err(
description: Tok<String>,
message: impl AsRef<str>,
posv: impl IntoIterator<Item = ErrPos>,
) -> OrcErr {
OrcErr {
description,
message: Arc::new(message.as_ref().to_string()),
positions: posv.into_iter().collect(),
}
pub fn mk_errv_floating(description: Tok<String>, message: impl AsRef<str>) -> OrcErrv {
mk_errv::<Pos>(description, message, [])
}
pub fn mk_errv<I: Into<ErrPos>>(
@@ -209,7 +200,12 @@ pub fn mk_errv<I: Into<ErrPos>>(
message: impl AsRef<str>,
posv: impl IntoIterator<Item = I>,
) -> OrcErrv {
mk_err(description, message, posv.into_iter().map_into()).into()
OrcErr {
description,
message: Arc::new(message.as_ref().to_string()),
positions: posv.into_iter().map_into().collect(),
}
.into()
}
pub async fn async_io_err<I: Into<ErrPos>>(

View File

@@ -0,0 +1,24 @@
use std::fmt;
use itertools::{Itertools, Position};
pub struct PrintList<'a, I: Iterator<Item = E> + Clone, E: fmt::Display>(pub I, pub &'a str);
impl<'a, I: Iterator<Item = E> + Clone, E: fmt::Display> fmt::Display for PrintList<'a, I, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (pos, item) in self.0.clone().with_position() {
match pos {
Position::First | Position::Only => write!(f, "{item}")?,
Position::Middle => write!(f, ", {item}")?,
Position::Last => write!(f, ", {} {item}", self.1)?,
}
}
Ok(())
}
}
pub trait IteratorPrint: Iterator<Item: fmt::Display> + Clone {
fn display<'a>(self, operator: &'a str) -> PrintList<'a, Self, Self::Item> {
PrintList(self, operator)
}
}
impl<T: Iterator<Item: fmt::Display> + Clone> IteratorPrint for T {}

View File

@@ -12,6 +12,7 @@ pub mod event;
pub mod format;
pub mod id_store;
pub mod interner;
pub mod iter_utils;
pub mod join;
pub mod location;
pub mod logging;

View File

@@ -1,4 +1,4 @@
/// A shorthand for mapping over enums with identical structure. Used for
/// A shorthand for mapping over enums with similar structure. Used for
/// converting between owned enums and the corresponding API enums that only
/// differ in the type of their fields.
///
@@ -7,7 +7,11 @@
/// match_mapping!(self, ThisType => OtherType {
/// EmptyVariant,
/// TupleVariant(foo => intern(foo), bar.clone()),
/// StructVariant{ a.to_api(), b }
/// StructVariant{ a.to_api(), b },
/// DedicatedConverter(value () convert)
/// } {
/// ThisType::DimorphicVariant(c) => OtherType::CorrespondingVariant(c.left(), c.right()),
/// ThisType::UnexpectedVariant => panic!(),
/// })
/// ```
#[macro_export]

View File

@@ -19,10 +19,9 @@ trait_set! {
pub trait NameIter = Iterator<Item = Tok<String>> + DoubleEndedIterator + ExactSizeIterator;
}
/// A token path which may be empty. [VName] is the non-empty,
/// [PathSlice] is the borrowed version
/// A token path which may be empty. [VName] is the non-empty version
#[derive(Clone, Default, Hash, PartialEq, Eq)]
pub struct VPath(pub Vec<Tok<String>>);
pub struct VPath(Vec<Tok<String>>);
impl VPath {
/// Collect segments into a vector
pub fn new(items: impl IntoIterator<Item = Tok<String>>) -> Self {

View File

@@ -3,7 +3,7 @@ use std::ops::Range;
use ordered_float::NotNan;
use crate::error::{OrcErr, mk_err};
use crate::error::{OrcErrv, mk_errv};
use crate::interner::Interner;
use crate::location::SrcRange;
use crate::name::Sym;
@@ -55,20 +55,20 @@ pub struct NumError {
pub kind: NumErrorKind,
}
pub async fn num_to_err(
pub async fn num_to_errv(
NumError { kind, range }: NumError,
offset: u32,
source: &Sym,
i: &Interner,
) -> OrcErr {
mk_err(
) -> OrcErrv {
mk_errv(
i.i("Failed to parse number").await,
match kind {
NumErrorKind::NaN => "NaN emerged during parsing",
NumErrorKind::InvalidDigit => "non-digit character encountered",
NumErrorKind::Overflow => "The number being described is too large or too accurate",
},
[SrcRange::new(offset + range.start as u32..offset + range.end as u32, source).pos().into()],
[SrcRange::new(offset + range.start as u32..offset + range.end as u32, source)],
)
}
@@ -92,11 +92,11 @@ pub fn parse_num(string: &str) -> Result<Numeric, NumError> {
match base_s.split_once('.') {
None => {
let base = int_parse(base_s, radix, pos)?;
if let Ok(pos_exp) = u32::try_from(exponent) {
if let Some(radical) = u64::from(radix).checked_pow(pos_exp) {
let num = base.checked_mul(radical).and_then(|m| m.try_into().ok()).ok_or(overflow_e)?;
return Ok(Numeric::Int(num));
}
if let Ok(pos_exp) = u32::try_from(exponent)
&& let Some(radical) = u64::from(radix).checked_pow(pos_exp)
{
let num = base.checked_mul(radical).and_then(|m| m.try_into().ok()).ok_or(overflow_e)?;
return Ok(Numeric::Int(num));
}
let f = (base as f64) * (radix as f64).powi(exponent);
let err = NumError { range: 0..string.len(), kind: NumErrorKind::NaN };

View File

@@ -7,11 +7,11 @@ use futures::future::join_all;
use itertools::Itertools;
use crate::api;
use crate::error::{OrcErrv, OrcRes, Reporter, mk_err, mk_errv};
use crate::error::{OrcErrv, OrcRes, Reporter, mk_errv};
use crate::format::{FmtCtx, FmtUnit, Format, fmt};
use crate::interner::{Interner, Tok};
use crate::location::SrcRange;
use crate::name::{NameLike, Sym, VName, VPath};
use crate::name::{Sym, VName, VPath};
use crate::tree::{ExprRepr, ExtraTok, Paren, TokTree, Token, ttv_fmt, ttv_range};
pub trait ParseCtx {
@@ -237,10 +237,10 @@ pub async fn parse_multiname<'a, A: ExprRepr, X: ExtraTok>(
match &tt.tok {
Token::NS(ns, body) => {
if !ns.starts_with(name_start) {
ctx.rep().report(mk_err(
ctx.rep().report(mk_errv(
ctx.i().i("Unexpected name prefix").await,
"Only names can precede ::",
[ttpos.into()],
[ttpos],
))
};
let out = Box::pin(rec(body, ctx)).await?;