First steps for the macro system
This commit is contained in:
@@ -158,6 +158,40 @@ impl fmt::Display for OrcErrv {
|
||||
|
||||
pub type OrcRes<T> = Result<T, OrcErrv>;
|
||||
|
||||
pub fn join_ok<T, U>(left: OrcRes<T>, right: OrcRes<U>) -> OrcRes<(T, U)> {
|
||||
match (left, right) {
|
||||
(Ok(t), Ok(u)) => Ok((t, u)),
|
||||
(Err(e), Ok(_)) | (Ok(_), Err(e)) => Err(e),
|
||||
(Err(e1), Err(e2)) => Err(e1 + e2),
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! join_ok {
|
||||
($($names:ident $(: $tys:ty)? = $vals:expr;)*) => {
|
||||
let $crate::join_ok!(@NAMES $($names $(: $tys)? = $vals;)*)
|
||||
:
|
||||
$crate::join_ok!(@TYPES $($names $(: $tys)? = $vals;)*)
|
||||
=
|
||||
$crate::join_ok!(@VALUES $($names $(: $tys)? = $vals;)*)?;
|
||||
};
|
||||
(@NAMES $name:ident $(: $ty:ty)? = $val:expr ; $($names:ident $(: $tys:ty)? = $vals:expr;)*) => {
|
||||
($name, $crate::join_ok!(@NAMES $($names $(: $tys)? = $vals;)*))
|
||||
};
|
||||
(@NAMES) => { _ };
|
||||
(@TYPES $name:ident : $ty:ty = $val:expr ; $($names:ident $(: $tys:ty)? = $vals:expr;)*) => {
|
||||
($ty, $crate::join_ok!(@TYPES $($names $(: $tys)? = $vals;)*))
|
||||
};
|
||||
(@TYPES $name:ident = $val:expr ; $($names:ident $(: $tys:ty)? = $vals:expr;)*) => {
|
||||
(_, $crate::join_ok!(@TYPES $($names $(: $tys)? = $vals;)*))
|
||||
};
|
||||
(@TYPES) => { () };
|
||||
(@VALUES $name:ident $(: $ty:ty)? = $val:expr ; $($names:ident $(: $tys:ty)? = $vals:expr;)*) => {
|
||||
$crate::error::join_ok($val, $crate::join_ok!(@VALUES $($names $(: $tys)? = $vals;)*))
|
||||
};
|
||||
(@VALUES) => { Ok(()) };
|
||||
}
|
||||
|
||||
pub fn mk_err(
|
||||
description: Tok<String>,
|
||||
message: impl AsRef<str>,
|
||||
|
||||
@@ -108,6 +108,10 @@ impl SrcRange {
|
||||
pub fn to_api(&self) -> api::SourceRange {
|
||||
api::SourceRange { path: self.path.to_api(), range: self.range.clone() }
|
||||
}
|
||||
pub fn to(&self, rhs: &Self) -> Self {
|
||||
assert_eq!(self.path, rhs.path, "Range continues across files");
|
||||
Self { path: self.path(), range: self.start().min(rhs.start())..self.end().max(rhs.end()) }
|
||||
}
|
||||
}
|
||||
impl From<SrcRange> for ErrPos {
|
||||
fn from(val: SrcRange) -> Self { val.pos().into() }
|
||||
|
||||
@@ -236,8 +236,8 @@ impl Sym {
|
||||
Self::from_tok(Tok::from_api(marker, i).await).expect("Empty sequence found for serialized Sym")
|
||||
}
|
||||
pub fn to_api(&self) -> api::TStrv { self.tok().to_api() }
|
||||
pub async fn push(&self, tok: Tok<String>, i: &Interner) -> Sym {
|
||||
Self::new(self.0.iter().cloned().chain([tok]), i).await.unwrap()
|
||||
pub async fn suffix(&self, tokv: impl IntoIterator<Item = Tok<String>>, i: &Interner) -> Sym {
|
||||
Self::new(self.0.iter().cloned().chain(tokv), i).await.unwrap()
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for Sym {
|
||||
|
||||
@@ -11,14 +11,14 @@ 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::name::{NameLike, Sym, VName, VPath};
|
||||
use crate::tree::{ExprRepr, ExtraTok, Paren, TokTree, Token, ttv_fmt, ttv_range};
|
||||
|
||||
pub trait ParseCtx {
|
||||
#[must_use]
|
||||
fn i(&self) -> &Interner;
|
||||
#[must_use]
|
||||
fn reporter(&self) -> &Reporter;
|
||||
fn rep(&self) -> &Reporter;
|
||||
}
|
||||
pub struct ParseCtxImpl<'a> {
|
||||
pub i: &'a Interner,
|
||||
@@ -26,7 +26,7 @@ pub struct ParseCtxImpl<'a> {
|
||||
}
|
||||
impl ParseCtx for ParseCtxImpl<'_> {
|
||||
fn i(&self) -> &Interner { self.i }
|
||||
fn reporter(&self) -> &Reporter { self.r }
|
||||
fn rep(&self) -> &Reporter { self.r }
|
||||
}
|
||||
|
||||
pub fn name_start(c: char) -> bool { c.is_alphabetic() || c == '_' }
|
||||
@@ -237,7 +237,7 @@ pub async fn parse_multiname<'a, A: ExprRepr, X: ExtraTok>(
|
||||
match &tt.tok {
|
||||
Token::NS(ns, body) => {
|
||||
if !ns.starts_with(name_start) {
|
||||
ctx.reporter().report(mk_err(
|
||||
ctx.rep().report(mk_err(
|
||||
ctx.i().i("Unexpected name prefix").await,
|
||||
"Only names can precede ::",
|
||||
[ttpos.into()],
|
||||
@@ -257,7 +257,7 @@ pub async fn parse_multiname<'a, A: ExprRepr, X: ExtraTok>(
|
||||
while let Some((output, tail)) = body.pop_front() {
|
||||
match rec(output, ctx).boxed_local().await {
|
||||
Ok(names) => o.extend(names),
|
||||
Err(e) => ctx.reporter().report(e),
|
||||
Err(e) => ctx.rep().report(e),
|
||||
}
|
||||
body = tail;
|
||||
}
|
||||
@@ -296,6 +296,10 @@ impl Import {
|
||||
None => self.path.into_name().expect("Import cannot be empty"),
|
||||
}
|
||||
}
|
||||
pub fn new(sr: SrcRange, path: VPath, name: Tok<String>) -> Self {
|
||||
Import { path, name: Some(name), sr }
|
||||
}
|
||||
pub fn new_glob(sr: SrcRange, path: VPath) -> Self { Import { path, name: None, sr } }
|
||||
}
|
||||
impl Display for Import {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::error::OrcErrv;
|
||||
use crate::format::{FmtCtx, FmtUnit, Format, Variants};
|
||||
use crate::interner::{Interner, Tok};
|
||||
use crate::location::{Pos, SrcRange};
|
||||
use crate::name::Sym;
|
||||
use crate::name::{Sym, VName, VPath};
|
||||
use crate::parse::Snippet;
|
||||
use crate::{api, match_mapping, tl_cache};
|
||||
|
||||
@@ -149,6 +149,20 @@ impl<H: ExprRepr, X: ExtraTok> TokTree<H, X> {
|
||||
pub fn as_name(&self) -> Option<Tok<String>> {
|
||||
if let Token::Name(n) = &self.tok { Some(n.clone()) } else { None }
|
||||
}
|
||||
pub fn as_multiname(&self) -> Result<VName, &TokTree<H, X>> {
|
||||
let mut segs = VPath::new([]);
|
||||
let mut cur = self;
|
||||
loop {
|
||||
match &cur.tok {
|
||||
Token::Name(last) => return Ok(segs.name_with_suffix(last.clone())),
|
||||
Token::NS(seg, inner) => {
|
||||
segs = segs.suffix([seg.clone()]);
|
||||
cur = inner;
|
||||
},
|
||||
_ => return Err(cur),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn as_s(&self, par: Paren) -> Option<Snippet<'_, H, X>> {
|
||||
self.tok.as_s(par).map(|slc| Snippet::new(self, slc))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user