Various progress, doesnt compile

Added prelude, made lambdas a single-token prefix like NS, made progress on implementations, removed const line type
This commit is contained in:
2025-07-31 00:30:41 +02:00
parent 19f2c6426a
commit 769c6cfc9f
31 changed files with 450 additions and 250 deletions

View File

@@ -1,8 +1,8 @@
#[macro_export]
macro_rules! clone {
($($n:ident),+; $body:expr) => (
($($n:ident $($mut:ident)?),+; $body:expr) => (
{
$( let $n = $n.clone(); )+
$( let $($mut)? $n = $n.clone(); )+
$body
}
);

View File

@@ -15,7 +15,7 @@ trait_set! {
pub trait GetSrc = FnMut(&Sym) -> Tok<String>;
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Pos {
None,
SlotTarget,

View File

@@ -272,34 +272,34 @@ pub trait NameLike:
/// Convert into held slice
fn as_slice(&self) -> &[Tok<String>] { Borrow::<[Tok<String>]>::borrow(self) }
/// Get iterator over tokens
fn iter(&self) -> impl NameIter + '_ { self.as_slice().iter().cloned() }
fn segs(&self) -> impl NameIter + '_ { self.as_slice().iter().cloned() }
/// Get iterator over string segments
fn str_iter(&self) -> impl Iterator<Item = &'_ str> + '_ {
self.as_slice().iter().map(|t| t.as_str())
}
/// Fully resolve the name for printing
#[must_use]
fn to_strv(&self) -> Vec<String> { self.iter().map(|s| s.to_string()).collect() }
fn to_strv(&self) -> Vec<String> { self.segs().map(|s| s.to_string()).collect() }
/// Format the name as an approximate filename
fn as_src_path(&self) -> String { format!("{}.orc", self.iter().join("/")) }
fn as_src_path(&self) -> String { format!("{}.orc", self.segs().join("/")) }
/// Return the number of segments in the name
fn len(&self) -> NonZeroUsize {
NonZeroUsize::try_from(self.iter().count()).expect("NameLike never empty")
fn len_nz(&self) -> NonZeroUsize {
NonZeroUsize::try_from(self.segs().count()).expect("NameLike never empty")
}
/// Like slice's `split_first` except we know that it always returns Some
fn split_first(&self) -> (Tok<String>, &[Tok<String>]) {
fn split_first_seg(&self) -> (Tok<String>, &[Tok<String>]) {
let (foot, torso) = self.as_slice().split_last().expect("NameLike never empty");
(foot.clone(), torso)
}
/// Like slice's `split_last` except we know that it always returns Some
fn split_last(&self) -> (Tok<String>, &[Tok<String>]) {
fn split_last_seg(&self) -> (Tok<String>, &[Tok<String>]) {
let (foot, torso) = self.as_slice().split_last().expect("NameLike never empty");
(foot.clone(), torso)
}
/// Get the first element
fn first(&self) -> Tok<String> { self.split_first().0 }
fn first_seg(&self) -> Tok<String> { self.split_first_seg().0 }
/// Get the last element
fn last(&self) -> Tok<String> { self.split_last().0 }
fn last_seg(&self) -> Tok<String> { self.split_last_seg().0 }
}
impl NameLike for Sym {}

View File

@@ -7,12 +7,12 @@ use futures::future::join_all;
use itertools::Itertools;
use crate::api;
use crate::error::{OrcRes, Reporter, mk_err, mk_errv};
use crate::format::fmt;
use crate::error::{OrcErrv, OrcRes, Reporter, mk_err, mk_errv};
use crate::format::{FmtCtx, FmtUnit, Format, fmt};
use crate::interner::{Interner, Tok};
use crate::location::SrcRange;
use crate::name::{Sym, VName, VPath};
use crate::tree::{ExprRepr, ExtraTok, Paren, TokTree, Token, ttv_range};
use crate::tree::{ExprRepr, ExtraTok, Paren, TokTree, Token, ttv_fmt, ttv_range};
pub trait ParseCtx {
#[must_use]
@@ -95,18 +95,10 @@ impl<A: ExprRepr, X: ExtraTok> Deref for Snippet<'_, A, X> {
type Target = [TokTree<A, X>];
fn deref(&self) -> &Self::Target { self.cur }
}
/// Remove tokens that aren't meaningful in expression context, such as comments
/// or line breaks
pub fn strip_fluff<A: ExprRepr, X: ExtraTok>(tt: &TokTree<A, X>) -> Option<TokTree<A, X>> {
let tok = match &tt.tok {
Token::BR => return None,
Token::Comment(_) => return None,
Token::LambdaHead(arg) => Token::LambdaHead(arg.iter().filter_map(strip_fluff).collect()),
Token::S(p, b) => Token::S(*p, b.iter().filter_map(strip_fluff).collect()),
t => t.clone(),
};
Some(TokTree { tok, sr: tt.sr.clone() })
impl<A: ExprRepr, X: ExtraTok> Format for Snippet<'_, A, X> {
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
ttv_fmt(&**self, c).await
}
}
#[derive(Clone, Debug)]
@@ -208,6 +200,15 @@ pub async fn expect_tok<'a, A: ExprRepr, X: ExtraTok>(
}
}
pub async fn token_errv<A: ExprRepr, X: ExtraTok>(
ctx: &impl ParseCtx,
tok: &TokTree<A, X>,
description: &'static str,
message: impl FnOnce(&str) -> String,
) -> OrcErrv {
mk_errv(ctx.i().i(description).await, message(&fmt(tok, ctx.i()).await), [tok.sr.pos()])
}
pub struct Parsed<'a, T, H: ExprRepr, X: ExtraTok> {
pub output: T,
pub tail: Snippet<'a, H, X>,

View File

@@ -62,8 +62,7 @@ pub fn recur<H: ExprRepr, X: ExtraTok>(
tok @ (Token::BR | Token::Bottom(_) | Token::Comment(_) | Token::Name(_)) => tok,
tok @ (Token::Handle(_) | Token::NewExpr(_)) => tok,
Token::NS(n, b) => Token::NS(n, Box::new(recur(*b, f))),
Token::LambdaHead(arg) =>
Token::LambdaHead(arg.into_iter().map(|tt| recur(tt, f)).collect_vec()),
Token::LambdaHead(arg) => Token::LambdaHead(Box::new(recur(*arg, f))),
Token::S(p, b) => Token::S(p, b.into_iter().map(|tt| recur(tt, f)).collect_vec()),
};
TokTree { sr: range, tok }
@@ -117,7 +116,7 @@ impl<H: ExprRepr, X: ExtraTok> TokTree<H, X> {
NS(n => Tok::from_api(*n, i).await,
b => Box::new(Self::from_api(b, hctx, xctx, src, i).boxed_local().await)),
Bottom(e => OrcErrv::from_api(e, i).await),
LambdaHead(arg => ttv_from_api(arg, hctx, xctx, src, i).await),
LambdaHead(arg => Box::new(Self::from_api(arg, hctx, xctx, src, i).boxed_local().await)),
Name(n => Tok::from_api(*n, i).await),
S(*par, b => ttv_from_api(b, hctx, xctx, src, i).await),
Comment(c.clone()),
@@ -137,7 +136,7 @@ impl<H: ExprRepr, X: ExtraTok> TokTree<H, X> {
NS(n.to_api(), b => Box::new(b.into_api(hctx, xctx).boxed_local().await)),
Bottom(e.to_api()),
Comment(c.clone()),
LambdaHead(arg => ttv_into_api(arg, hctx, xctx).boxed_local().await),
LambdaHead(arg => Box::new(arg.into_api(hctx, xctx).boxed_local().await)),
Name(nn.to_api()),
S(p, b => ttv_into_api(b, hctx, xctx).boxed_local().await),
Handle(hand.into_api(hctx).await),
@@ -153,18 +152,18 @@ impl<H: ExprRepr, X: ExtraTok> TokTree<H, X> {
pub fn as_s(&self, par: Paren) -> Option<Snippet<'_, H, X>> {
self.tok.as_s(par).map(|slc| Snippet::new(self, slc))
}
pub fn as_lambda(&self) -> Option<Snippet<'_, H, X>> {
pub fn as_lambda(&self) -> Option<&Self> {
match &self.tok {
Token::LambdaHead(arg) => Some(Snippet::new(self, arg)),
Token::LambdaHead(arg) => Some(&**arg),
_ => None,
}
}
pub fn is_fluff(&self) -> bool { matches!(self.tok, Token::Comment(_) | Token::BR) }
pub fn lambda(arg: Vec<Self>, mut body: Vec<Self>) -> Self {
let arg_range = ttv_range(&arg).expect("Lambda with empty arg!");
pub fn lambda(arg: Self, mut body: Vec<Self>) -> Self {
let arg_range = arg.sr();
let mut s_range = arg_range.clone();
s_range.range.end = body.last().expect("Lambda with empty body!").sr.range.end;
body.insert(0, Token::LambdaHead(arg).at(arg_range));
body.insert(0, Token::LambdaHead(Box::new(arg)).at(arg_range));
Token::S(Paren::Round, body).at(s_range)
}
pub fn sr(&self) -> SrcRange { self.sr.clone() }
@@ -230,7 +229,7 @@ pub enum Token<H: ExprRepr, X: ExtraTok> {
Comment(Rc<String>),
/// The part of a lambda between `\` and `.` enclosing the argument. The body
/// stretches to the end of the enclosing parens or the end of the const line
LambdaHead(Vec<TokTree<H, X>>),
LambdaHead(Box<TokTree<H, X>>),
/// A binding, operator, or a segment of a namespaced::name
Name(Tok<String>),
/// A namespace prefix, like `my_ns::` followed by a token
@@ -267,7 +266,7 @@ impl<H: ExprRepr, X: ExtraTok> Format for Token<H, X> {
Self::Comment(c) => format!("--[{c}]--").into(),
Self::LambdaHead(arg) =>
tl_cache!(Rc<Variants>: Rc::new(Variants::default().bounded("\\{0b}.")))
.units([ttv_fmt(arg, c).await]),
.units([arg.print(c).boxed_local().await]),
Self::NS(n, b) => tl_cache!(Rc<Variants>: Rc::new(Variants::default().bounded("{0}::{1l}")))
.units([n.to_string().into(), b.print(c).boxed_local().await]),
Self::Name(n) => format!("{n}").into(),