temp commit
This commit is contained in:
@@ -10,10 +10,11 @@ use hashbrown::HashSet;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::OrcErrv;
|
||||
use orchid_base::format::{FmtCtx, FmtUnit, Format, Variants};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::interner::Interner;
|
||||
use orchid_base::location::{Pos, SrcRange};
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::tl_cache;
|
||||
use orchid_base::tree::{AtomRepr, indent};
|
||||
use orchid_base::tree::{AtomRepr, TokenVariant, indent};
|
||||
use substack::Substack;
|
||||
|
||||
use crate::api;
|
||||
@@ -22,9 +23,9 @@ use crate::ctx::Ctx;
|
||||
use crate::expr_store::ExprStore;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExprParseCtx {
|
||||
pub ctx: Ctx,
|
||||
pub exprs: ExprStore,
|
||||
pub struct ExprParseCtx<'a> {
|
||||
pub ctx: &'a Ctx,
|
||||
pub exprs: &'a ExprStore,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -36,6 +37,7 @@ pub struct ExprData {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Expr(Rc<ExprData>);
|
||||
impl Expr {
|
||||
#[must_use]
|
||||
pub fn pos(&self) -> Pos { self.0.pos.clone() }
|
||||
pub async fn try_into_owned_atom(self) -> Result<AtomHand, Self> {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
@@ -46,25 +48,29 @@ impl Expr {
|
||||
},
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn as_atom(&self) -> Option<AtomHand> {
|
||||
if let ExprKind::Atom(a) = &*self.kind().read().await { Some(a.clone()) } else { None }
|
||||
}
|
||||
#[must_use]
|
||||
pub fn strong_count(&self) -> usize { Rc::strong_count(&self.0) }
|
||||
#[must_use]
|
||||
pub fn id(&self) -> api::ExprTicket {
|
||||
api::ExprTicket(
|
||||
NonZeroU64::new(self.0.as_ref() as *const ExprData as usize as u64)
|
||||
.expect("this is a ref, it cannot be null"),
|
||||
)
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn from_api(
|
||||
api: &api::Expression,
|
||||
psb: PathSetBuilder<'_, u64>,
|
||||
ctx: &mut ExprParseCtx,
|
||||
ctx: &mut ExprParseCtx<'_>,
|
||||
) -> Self {
|
||||
let pos = Pos::from_api(&api.location, &ctx.ctx.i).await;
|
||||
let kind = match &api.kind {
|
||||
api::ExpressionKind::Arg(n) => {
|
||||
assert!(psb.register_arg(&n), "Arguments must be enclosed in a matching lambda");
|
||||
assert!(psb.register_arg(n), "Arguments must be enclosed in a matching lambda");
|
||||
ExprKind::Arg
|
||||
},
|
||||
api::ExpressionKind::Bottom(bot) =>
|
||||
@@ -72,14 +78,14 @@ impl Expr {
|
||||
api::ExpressionKind::Call(f, x) => {
|
||||
let (lpsb, rpsb) = psb.split();
|
||||
ExprKind::Call(
|
||||
Expr::from_api(&f, lpsb, ctx).boxed_local().await,
|
||||
Expr::from_api(&x, rpsb, ctx).boxed_local().await,
|
||||
Expr::from_api(f, lpsb, ctx).boxed_local().await,
|
||||
Expr::from_api(x, rpsb, ctx).boxed_local().await,
|
||||
)
|
||||
},
|
||||
api::ExpressionKind::Const(name) => ExprKind::Const(Sym::from_api(*name, &ctx.ctx.i).await),
|
||||
api::ExpressionKind::Lambda(x, body) => {
|
||||
let lbuilder = psb.lambda(&x);
|
||||
let body = Expr::from_api(&body, lbuilder.stack(), ctx).boxed_local().await;
|
||||
let lbuilder = psb.lambda(x);
|
||||
let body = Expr::from_api(body, lbuilder.stack(), ctx).boxed_local().await;
|
||||
ExprKind::Lambda(lbuilder.collect(), body)
|
||||
},
|
||||
api::ExpressionKind::NewAtom(a) =>
|
||||
@@ -88,13 +94,14 @@ impl Expr {
|
||||
api::ExpressionKind::Seq(a, b) => {
|
||||
let (apsb, bpsb) = psb.split();
|
||||
ExprKind::Seq(
|
||||
Expr::from_api(&a, apsb, ctx).boxed_local().await,
|
||||
Expr::from_api(&b, bpsb, ctx).boxed_local().await,
|
||||
Expr::from_api(a, apsb, ctx).boxed_local().await,
|
||||
Expr::from_api(b, bpsb, ctx).boxed_local().await,
|
||||
)
|
||||
},
|
||||
};
|
||||
Self(Rc::new(ExprData { pos, kind: RwLock::new(kind) }))
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn to_api(&self) -> api::InspectedKind {
|
||||
use api::InspectedKind as K;
|
||||
match &*self.0.kind.read().await {
|
||||
@@ -104,6 +111,7 @@ impl Expr {
|
||||
_ => K::Opaque,
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn kind(&self) -> &RwLock<ExprKind> { &self.0.kind }
|
||||
}
|
||||
impl Format for Expr {
|
||||
@@ -139,6 +147,7 @@ pub enum ExprKind {
|
||||
Missing,
|
||||
}
|
||||
impl ExprKind {
|
||||
#[must_use]
|
||||
pub fn at(self, pos: Pos) -> Expr { Expr(Rc::new(ExprData { pos, kind: RwLock::new(self) })) }
|
||||
}
|
||||
impl Format for ExprKind {
|
||||
@@ -198,13 +207,16 @@ pub enum PathSetFrame<'a, T: PartialEq> {
|
||||
#[derive(Clone)]
|
||||
pub struct PathSetBuilder<'a, T: PartialEq>(Substack<'a, PathSetFrame<'a, T>>);
|
||||
impl<'a, T: PartialEq> PathSetBuilder<'a, T> {
|
||||
#[must_use]
|
||||
pub fn new() -> Self { Self(Substack::Bottom) }
|
||||
#[must_use]
|
||||
pub fn split(&'a self) -> (Self, Self) {
|
||||
(
|
||||
Self(self.0.push(PathSetFrame::Step(Step::Left))),
|
||||
Self(self.0.push(PathSetFrame::Step(Step::Right))),
|
||||
)
|
||||
}
|
||||
#[must_use]
|
||||
pub fn lambda<'b>(self, arg: &'b T) -> LambdaBuilder<'b, T>
|
||||
where 'a: 'b {
|
||||
LambdaBuilder { arg, path: RefCell::default(), stack: self }
|
||||
@@ -264,15 +276,21 @@ impl<'a, T: PartialEq> PathSetBuilder<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: PartialEq> Default for PathSetBuilder<'a, T> {
|
||||
fn default() -> Self { Self::new() }
|
||||
}
|
||||
|
||||
pub struct LambdaBuilder<'a, T: PartialEq> {
|
||||
arg: &'a T,
|
||||
path: RefCell<Option<PathSet>>,
|
||||
stack: PathSetBuilder<'a, T>,
|
||||
}
|
||||
impl<'a, T: PartialEq> LambdaBuilder<'a, T> {
|
||||
#[must_use]
|
||||
pub fn stack(&'a self) -> PathSetBuilder<'a, T> {
|
||||
PathSetBuilder(self.stack.0.push(PathSetFrame::Lambda(self.arg, &self.path)))
|
||||
}
|
||||
#[must_use]
|
||||
pub fn collect(self) -> Option<PathSet> { self.path.into_inner() }
|
||||
}
|
||||
|
||||
@@ -285,6 +303,7 @@ pub struct PathSet {
|
||||
pub next: Option<(Box<PathSet>, Box<PathSet>)>,
|
||||
}
|
||||
impl PathSet {
|
||||
#[must_use]
|
||||
pub fn next(&self) -> Option<(&PathSet, &PathSet)> {
|
||||
self.next.as_ref().map(|(l, r)| (&**l, &**r))
|
||||
}
|
||||
@@ -305,6 +324,7 @@ impl fmt::Display for PathSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn bot_expr(err: impl Into<OrcErrv>) -> Expr {
|
||||
let errv: OrcErrv = err.into();
|
||||
let pos = errv.pos_iter().next().map_or(Pos::None, |ep| ep.position.clone());
|
||||
@@ -313,5 +333,44 @@ pub fn bot_expr(err: impl Into<OrcErrv>) -> Expr {
|
||||
|
||||
pub struct WeakExpr(Weak<ExprData>);
|
||||
impl WeakExpr {
|
||||
#[must_use]
|
||||
pub fn upgrade(&self) -> Option<Expr> { self.0.upgrade().map(Expr) }
|
||||
}
|
||||
|
||||
impl TokenVariant<api::ExprTicket> for Expr {
|
||||
type FromApiCtx<'a> = ExprStore;
|
||||
async fn from_api(
|
||||
api: &api::ExprTicket,
|
||||
ctx: &mut Self::FromApiCtx<'_>,
|
||||
_: SrcRange,
|
||||
_: &Interner,
|
||||
) -> Self {
|
||||
ctx.get_expr(*api).expect("Invalid ticket")
|
||||
}
|
||||
type ToApiCtx<'a> = ExprStore;
|
||||
async fn into_api(self, ctx: &mut Self::ToApiCtx<'_>) -> api::ExprTicket {
|
||||
let id = self.id();
|
||||
ctx.give_expr(self);
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
/// Acknowledgment that expr serialization is impossible and thus will panic.
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct ExprWillPanic;
|
||||
|
||||
impl TokenVariant<api::Expression> for Expr {
|
||||
type FromApiCtx<'a> = ExprParseCtx<'a>;
|
||||
async fn from_api(
|
||||
api: &api::Expression,
|
||||
ctx: &mut Self::FromApiCtx<'_>,
|
||||
_: SrcRange,
|
||||
_: &Interner,
|
||||
) -> Self {
|
||||
Self::from_api(api, PathSetBuilder::new(), ctx).await
|
||||
}
|
||||
type ToApiCtx<'a> = ExprWillPanic;
|
||||
async fn into_api(self, ExprWillPanic: &mut Self::ToApiCtx<'_>) -> api::Expression {
|
||||
panic!("Cannot serialize expr!")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user