tamer: asg::air: Eliminate parent context from AirExprAggregate
This does the same thing to `AirExprAggregate` that was previously done for `AirAggregate`, taking all parent context from the stack. This results in a fairly significant simplification of the code, which is nice, and it makes the `RootStrategy` obviously obsolete in the dangling case, which will result in more refactoring to simplify it even more. I regret not taking this route to begin with, but not only was I hoping I wouldn't need to, but I was still deriving the graph structure and wasn't sure how this would eventually turn out. These commits serve as a proof of necessity. Or, at least, concrete rationale. It's worth noting that this also introduces `From` implementations for `AirAggregate` and the child parsers, and then uses _that_ to push context from the `AirTplAggregate` parser. This means that we're just about ready for it to serve as a superstate. But there is still a specialization of `AirExprAggregate` in that `From` impl, which must be removed. DEV-13708main
parent
755c91e04a
commit
525adb8a6c
|
@ -39,7 +39,7 @@ use self::expr::AirExprAggregateReachable;
|
|||
|
||||
use super::{
|
||||
graph::object::{ObjectIndexTo, Pkg, Tpl},
|
||||
Asg, AsgError, Ident, ObjectIndex,
|
||||
Asg, AsgError, Expr, Ident, ObjectIndex,
|
||||
};
|
||||
use crate::{
|
||||
diagnose::Annotate, diagnostic_todo, parse::prelude::*, sym::SymbolId,
|
||||
|
@ -73,7 +73,7 @@ pub enum AirAggregate {
|
|||
/// This expects to inherit an [`AirExprAggregate`] from the prior state
|
||||
/// so that we are not continuously re-allocating its stack for each
|
||||
/// new expression root.
|
||||
PkgExpr(AirExprAggregateReachable<Pkg>),
|
||||
PkgExpr(AirExprAggregateReachable),
|
||||
|
||||
/// Parser is in template parsing mode.
|
||||
///
|
||||
|
@ -102,6 +102,18 @@ impl Display for AirAggregate {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<AirExprAggregateReachable> for AirAggregate {
|
||||
fn from(st: AirExprAggregateReachable) -> Self {
|
||||
Self::PkgExpr(st)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AirTplAggregate> for AirAggregate {
|
||||
fn from(st: AirTplAggregate) -> Self {
|
||||
Self::PkgTpl(st)
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseState for AirAggregate {
|
||||
type Token = Air;
|
||||
type Object = ();
|
||||
|
@ -160,7 +172,7 @@ impl ParseState for AirAggregate {
|
|||
|
||||
(Toplevel(oi_pkg), tok @ AirExpr(..)) => {
|
||||
ctx.push(Toplevel(oi_pkg));
|
||||
let expr = AirExprAggregate::new_in(oi_pkg);
|
||||
let expr = AirExprAggregate::new();
|
||||
Transition(PkgExpr(expr)).incomplete().with_lookahead(tok)
|
||||
}
|
||||
|
||||
|
@ -293,8 +305,8 @@ impl AirAggregate {
|
|||
/// [`crate::parse`] framework.
|
||||
fn delegate_expr(
|
||||
ctx: &mut <Self as ParseState>::Context,
|
||||
expr: AirExprAggregateReachable<Pkg>,
|
||||
etok: impl Into<<AirExprAggregateReachable<Pkg> as ParseState>::Token>,
|
||||
expr: AirExprAggregateReachable,
|
||||
etok: impl Into<<AirExprAggregateReachable as ParseState>::Token>,
|
||||
) -> TransitionResult<Self> {
|
||||
let tok = etok.into();
|
||||
|
||||
|
@ -356,9 +368,9 @@ impl AirAggregateCtx {
|
|||
self.as_mut()
|
||||
}
|
||||
|
||||
fn push(&mut self, st: AirAggregate) {
|
||||
fn push<S: Into<AirAggregate>>(&mut self, st: S) {
|
||||
let Self(_, stack) = self;
|
||||
stack.push(st);
|
||||
stack.push(st.into());
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Option<AirAggregate> {
|
||||
|
@ -373,9 +385,9 @@ impl AirAggregateCtx {
|
|||
fn rooting_oi(&self) -> Option<ObjectIndexTo<Ident>> {
|
||||
let Self(_, stack) = self;
|
||||
|
||||
stack.iter().rev().find_map(|st| match *st {
|
||||
stack.iter().rev().find_map(|st| match st {
|
||||
AirAggregate::Empty => None,
|
||||
AirAggregate::Toplevel(pkg_oi) => Some(pkg_oi.into()),
|
||||
AirAggregate::Toplevel(pkg_oi) => Some((*pkg_oi).into()),
|
||||
|
||||
// Expressions never serve as roots for identifiers;
|
||||
// this will always fall through to the parent context.
|
||||
|
@ -383,8 +395,46 @@ impl AirAggregateCtx {
|
|||
// the next frame should succeed.
|
||||
AirAggregate::PkgExpr(_) => None,
|
||||
|
||||
AirAggregate::PkgTpl(_) => {
|
||||
diagnostic_todo!(vec![], "PkgTpl rooting_oi")
|
||||
// Identifiers bound while within a template definition context
|
||||
// must bind to the eventual _expansion_ site,
|
||||
// as if the body were pasted there.
|
||||
// Templates must therefore serve as containers for identifiers
|
||||
// bound therein.
|
||||
AirAggregate::PkgTpl(tplst) => {
|
||||
tplst.active_tpl_oi().map(Into::into)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// The active dangling expression context for [`Expr`]s.
|
||||
///
|
||||
/// A value of [`None`] indicates that expressions are not permitted to
|
||||
/// dangle in the current context
|
||||
/// (and so must be identified).
|
||||
fn dangling_expr_oi(&self) -> Option<ObjectIndexTo<Expr>> {
|
||||
let Self(_, stack) = self;
|
||||
|
||||
stack.iter().rev().find_map(|st| match st {
|
||||
AirAggregate::Empty => None,
|
||||
|
||||
// A dangling expression in a package context would be
|
||||
// unreachable.
|
||||
// There should be no parent frame and so this will fail to find
|
||||
// a value.
|
||||
AirAggregate::Toplevel(_) => None,
|
||||
|
||||
// Expressions may always contain other expressions,
|
||||
// and so this method should not be consulted in such a
|
||||
// context.
|
||||
// Nonetheless,
|
||||
// fall through to the parent frame and give a correct answer.
|
||||
AirAggregate::PkgExpr(_) => None,
|
||||
|
||||
// Templates serve as containers for dangling expressions,
|
||||
// since they may expand into an context where they are not
|
||||
// considered to be dangling.
|
||||
AirAggregate::PkgTpl(tplst) => {
|
||||
tplst.active_tpl_oi().map(Into::into)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -31,13 +31,12 @@ use super::{
|
|||
};
|
||||
use crate::{
|
||||
asg::{
|
||||
graph::object::{ObjectIndexRelTo, ObjectIndexTo, ObjectRelTo},
|
||||
graph::object::{ObjectIndexRelTo, ObjectIndexTo},
|
||||
Ident, ObjectKind,
|
||||
},
|
||||
f::Functor,
|
||||
parse::prelude::*,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[cfg(doc)]
|
||||
use StackEdge::{Dangling, Reachable};
|
||||
|
@ -46,14 +45,13 @@ use StackEdge::{Dangling, Reachable};
|
|||
/// with expression roots bound to their associated [`Ident`]s.
|
||||
///
|
||||
/// See [`ReachableOnly`] for more information.
|
||||
pub type AirExprAggregateReachable<O> = AirExprAggregate<O, ReachableOnly<O>>;
|
||||
pub type AirExprAggregateReachable = AirExprAggregate<ReachableOnly>;
|
||||
|
||||
/// Parse and aggregate both [`Reachable`] and [`Dangling`] [`Expr`]s into
|
||||
/// the graph.
|
||||
///
|
||||
/// See [`StoreDangling`] for more information.
|
||||
pub type AirExprAggregateStoreDangling<O> =
|
||||
AirExprAggregate<O, StoreDangling<O>>;
|
||||
pub type AirExprAggregateStoreDangling = AirExprAggregate<StoreDangling>;
|
||||
|
||||
/// Parse an AIR expression with binding support.
|
||||
///
|
||||
|
@ -65,19 +63,19 @@ pub type AirExprAggregateStoreDangling<O> =
|
|||
/// handles each of its tokens and performs error recovery on invalid
|
||||
/// state transitions.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum AirExprAggregate<O: ObjectKind, S: RootStrategy<O>> {
|
||||
pub enum AirExprAggregate<S: RootStrategy> {
|
||||
/// Ready for an expression;
|
||||
/// expression stack is empty.
|
||||
Ready(S, ExprStack<Dormant>, PhantomData<O>),
|
||||
Ready(S, ExprStack<Dormant>),
|
||||
|
||||
/// Building an expression.
|
||||
BuildingExpr(S, ExprStack<Active>, ObjectIndex<Expr>),
|
||||
}
|
||||
|
||||
impl<O: ObjectKind, S: RootStrategy<O>> Display for AirExprAggregate<O, S> {
|
||||
impl<S: RootStrategy> Display for AirExprAggregate<S> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Ready(_, es, _) => {
|
||||
Self::Ready(_, es) => {
|
||||
write!(f, "ready for expression with {es}")
|
||||
}
|
||||
Self::BuildingExpr(_, es, _) => {
|
||||
|
@ -87,7 +85,7 @@ impl<O: ObjectKind, S: RootStrategy<O>> Display for AirExprAggregate<O, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<O: ObjectKind, S: RootStrategy<O>> ParseState for AirExprAggregate<O, S> {
|
||||
impl<S: RootStrategy> ParseState for AirExprAggregate<S> {
|
||||
type Token = AirBindableExpr;
|
||||
type Object = ();
|
||||
type Error = AsgError;
|
||||
|
@ -103,7 +101,7 @@ impl<O: ObjectKind, S: RootStrategy<O>> ParseState for AirExprAggregate<O, S> {
|
|||
use AirExprAggregate::*;
|
||||
|
||||
match (self, tok) {
|
||||
(Ready(root, es, _), AirExpr(ExprStart(op, span))) => {
|
||||
(Ready(root, es), AirExpr(ExprStart(op, span))) => {
|
||||
let oi = ctx.asg_mut().create(Expr::new(op, span));
|
||||
Transition(BuildingExpr(root, es.activate(), oi)).incomplete()
|
||||
}
|
||||
|
@ -119,24 +117,18 @@ impl<O: ObjectKind, S: RootStrategy<O>> ParseState for AirExprAggregate<O, S> {
|
|||
});
|
||||
|
||||
let dangling = es.is_dangling();
|
||||
let oi_root = ctx.dangling_expr_oi();
|
||||
|
||||
match (es.pop(), dangling) {
|
||||
((es, Some(poi)), _) => {
|
||||
Transition(BuildingExpr(root, es, poi)).incomplete()
|
||||
}
|
||||
((es, None), true) => {
|
||||
root.hold_dangling(ctx.asg_mut(), oi).transition(Ready(
|
||||
root,
|
||||
es.done(),
|
||||
PhantomData::default(),
|
||||
))
|
||||
((es, None), true) => root
|
||||
.hold_dangling(ctx.asg_mut(), oi_root, oi)
|
||||
.transition(Ready(root, es.done())),
|
||||
((es, None), false) => {
|
||||
Transition(Ready(root, es.done())).incomplete()
|
||||
}
|
||||
((es, None), false) => Transition(Ready(
|
||||
root,
|
||||
es.done(),
|
||||
PhantomData::default(),
|
||||
))
|
||||
.incomplete(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,13 +172,9 @@ impl<O: ObjectKind, S: RootStrategy<O>> ParseState for AirExprAggregate<O, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<O: ObjectKind, S: RootStrategy<O>> AirExprAggregate<O, S> {
|
||||
pub(super) fn new_in(oi: ObjectIndex<O>) -> Self {
|
||||
Self::Ready(
|
||||
S::new_root(oi),
|
||||
ExprStack::default(),
|
||||
PhantomData::default(),
|
||||
)
|
||||
impl<S: RootStrategy> AirExprAggregate<S> {
|
||||
pub(super) fn new() -> Self {
|
||||
Self::Ready(S::new(), ExprStack::default())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,10 +380,10 @@ mod root {
|
|||
/// for the definition associated with this identifier.
|
||||
/// An identified expression will be rooted in [`Self`] even if it is a
|
||||
/// sub-expression.
|
||||
pub trait RootStrategy<O: ObjectKind>: Debug + PartialEq {
|
||||
pub trait RootStrategy: Debug + PartialEq {
|
||||
/// Declare `oi` as the root of all accepted [`Expr`]s produced by
|
||||
/// the parser.
|
||||
fn new_root(oi: ObjectIndex<O>) -> Self;
|
||||
fn new() -> Self;
|
||||
|
||||
/// Look up the provided identifier `id` on the [`Asg`] and indicate
|
||||
/// that its definition is associated with [`Self`]'s root.
|
||||
|
@ -417,6 +405,7 @@ mod root {
|
|||
fn hold_dangling(
|
||||
&self,
|
||||
asg: &mut Asg,
|
||||
oi_root: Option<ObjectIndexTo<Expr>>,
|
||||
oi_expr: ObjectIndex<Expr>,
|
||||
) -> Result<(), AsgError>;
|
||||
}
|
||||
|
@ -438,16 +427,11 @@ mod root {
|
|||
///
|
||||
/// See [`RootStrategy`] for more information.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ReachableOnly<O: ObjectKind>(ObjectIndex<O>)
|
||||
where
|
||||
O: ObjectRelTo<Ident>;
|
||||
pub struct ReachableOnly;
|
||||
|
||||
impl<O: ObjectKind> RootStrategy<O> for ReachableOnly<O>
|
||||
where
|
||||
O: ObjectRelTo<Ident>,
|
||||
{
|
||||
fn new_root(oi: ObjectIndex<O>) -> Self {
|
||||
Self(oi)
|
||||
impl RootStrategy for ReachableOnly {
|
||||
fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn defines(
|
||||
|
@ -456,16 +440,14 @@ mod root {
|
|||
oi_root: ObjectIndexTo<Ident>,
|
||||
id: SPair,
|
||||
) -> ObjectIndex<Ident> {
|
||||
match self {
|
||||
Self(_oi_root) => asg
|
||||
.lookup_global_or_missing(id)
|
||||
.add_edge_from(asg, oi_root, None),
|
||||
}
|
||||
asg.lookup_global_or_missing(id)
|
||||
.add_edge_from(asg, oi_root, None)
|
||||
}
|
||||
|
||||
fn hold_dangling(
|
||||
&self,
|
||||
asg: &mut Asg,
|
||||
_oi_root: Option<ObjectIndexTo<Expr>>,
|
||||
oi_expr: ObjectIndex<Expr>,
|
||||
) -> Result<(), AsgError> {
|
||||
Err(AsgError::DanglingExpr(oi_expr.resolve(asg).span()))
|
||||
|
@ -486,41 +468,33 @@ mod root {
|
|||
///
|
||||
/// See [`RootStrategy`] for more information.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct StoreDangling<O: ObjectKind>(ObjectIndex<O>)
|
||||
where
|
||||
O: ObjectRelTo<Ident> + ObjectRelTo<Expr>;
|
||||
pub struct StoreDangling;
|
||||
|
||||
impl<O: ObjectKind> RootStrategy<O> for StoreDangling<O>
|
||||
where
|
||||
O: ObjectRelTo<Ident> + ObjectRelTo<Expr>,
|
||||
{
|
||||
fn new_root(oi: ObjectIndex<O>) -> Self {
|
||||
Self(oi)
|
||||
impl RootStrategy for StoreDangling {
|
||||
fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn defines(
|
||||
&self,
|
||||
asg: &mut Asg,
|
||||
_oi_root: ObjectIndexTo<Ident>,
|
||||
oi_root: ObjectIndexTo<Ident>,
|
||||
name: SPair,
|
||||
) -> ObjectIndex<Ident> {
|
||||
// This cannot simply call [`ReachableOnly`]'s `defines` because
|
||||
// we cannot cache in the global environment.
|
||||
// This can be realized once caching is generalized;
|
||||
// see the commit that introduced this comment.
|
||||
match self {
|
||||
Self(oi_root) => oi_root.declare_local(asg, name),
|
||||
}
|
||||
oi_root.declare_local(asg, name)
|
||||
}
|
||||
|
||||
fn hold_dangling(
|
||||
&self,
|
||||
asg: &mut Asg,
|
||||
oi_root: Option<ObjectIndexTo<Expr>>,
|
||||
oi_expr: ObjectIndex<Expr>,
|
||||
) -> Result<(), AsgError> {
|
||||
let Self(oi_root) = self;
|
||||
|
||||
oi_root.add_edge_to(asg, oi_expr, None);
|
||||
oi_root.expect("TODO").add_edge_to(asg, oi_expr, None);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,17 +67,13 @@ pub enum AirTplAggregate {
|
|||
/// tokens that are received in this state are interpreted as directly
|
||||
/// applying to the template itself,
|
||||
/// or creating an object directly owned by the template.
|
||||
Toplevel(TplState, AirExprAggregateStoreDangling<Tpl>),
|
||||
Toplevel(TplState),
|
||||
|
||||
/// Defining a template metavariable.
|
||||
TplMeta(
|
||||
TplState,
|
||||
AirExprAggregateStoreDangling<Tpl>,
|
||||
ObjectIndex<Meta>,
|
||||
),
|
||||
TplMeta(TplState, ObjectIndex<Meta>),
|
||||
|
||||
/// Aggregating tokens into a template.
|
||||
TplExpr(TplState, AirExprAggregateStoreDangling<Tpl>),
|
||||
TplExpr(TplState, AirExprAggregateStoreDangling),
|
||||
}
|
||||
|
||||
impl Display for AirTplAggregate {
|
||||
|
@ -85,11 +81,13 @@ impl Display for AirTplAggregate {
|
|||
match self {
|
||||
Self::Ready => write!(f, "ready for template definition"),
|
||||
|
||||
Self::Toplevel(tpl, expr) | Self::TplExpr(tpl, expr) => {
|
||||
Self::Toplevel(tpl) => write!(f, "building {tpl} at toplevel"),
|
||||
|
||||
Self::TplExpr(tpl, expr) => {
|
||||
write!(f, "building {tpl} with {expr}")
|
||||
}
|
||||
|
||||
Self::TplMeta(tpl, _, _) => {
|
||||
Self::TplMeta(tpl, _) => {
|
||||
write!(f, "building {tpl} metavariable")
|
||||
}
|
||||
}
|
||||
|
@ -184,11 +182,7 @@ impl ParseState for AirTplAggregate {
|
|||
(Ready, AirTpl(TplStart(span))) => {
|
||||
let oi_tpl = ctx.asg_mut().create(Tpl::new(span));
|
||||
|
||||
Transition(Toplevel(
|
||||
TplState::Dangling(oi_tpl),
|
||||
AirExprAggregate::new_in(oi_tpl),
|
||||
))
|
||||
.incomplete()
|
||||
Transition(Toplevel(TplState::Dangling(oi_tpl))).incomplete()
|
||||
}
|
||||
|
||||
(Toplevel(..), AirTpl(TplStart(span))) => diagnostic_todo!(
|
||||
|
@ -196,7 +190,7 @@ impl ParseState for AirTplAggregate {
|
|||
"nested tpl open"
|
||||
),
|
||||
|
||||
(Toplevel(tpl, expr), AirBind(BindIdent(id))) => {
|
||||
(Toplevel(tpl), AirBind(BindIdent(id))) => {
|
||||
let oi_root = ctx.rooting_oi().expect("TODO");
|
||||
let asg = ctx.asg_mut();
|
||||
|
||||
|
@ -204,35 +198,31 @@ impl ParseState for AirTplAggregate {
|
|||
.bind_definition(asg, id, tpl.oi())
|
||||
.map(|oi_ident| oi_root.defines(asg, oi_ident))
|
||||
.map(|_| ())
|
||||
.transition(Toplevel(tpl.identify(id), expr))
|
||||
.transition(Toplevel(tpl.identify(id)))
|
||||
}
|
||||
|
||||
(Toplevel(tpl, expr), AirBind(RefIdent(id))) => {
|
||||
(Toplevel(tpl), AirBind(RefIdent(id))) => {
|
||||
tpl.oi().apply_named_tpl(ctx.asg_mut(), id);
|
||||
Transition(Toplevel(tpl, expr)).incomplete()
|
||||
Transition(Toplevel(tpl)).incomplete()
|
||||
}
|
||||
|
||||
(Toplevel(tpl, expr), AirTpl(TplMetaStart(span))) => {
|
||||
(Toplevel(tpl), AirTpl(TplMetaStart(span))) => {
|
||||
let oi_meta = ctx.asg_mut().create(Meta::new_required(span));
|
||||
Transition(TplMeta(tpl, expr, oi_meta)).incomplete()
|
||||
Transition(TplMeta(tpl, oi_meta)).incomplete()
|
||||
}
|
||||
(TplMeta(tpl, expr, oi_meta), AirTpl(TplMetaEnd(cspan))) => {
|
||||
(TplMeta(tpl, oi_meta), AirTpl(TplMetaEnd(cspan))) => {
|
||||
oi_meta.close(ctx.asg_mut(), cspan);
|
||||
Transition(Toplevel(tpl, expr)).incomplete()
|
||||
Transition(Toplevel(tpl)).incomplete()
|
||||
}
|
||||
|
||||
(TplMeta(tpl, expr, oi_meta), AirTpl(TplLexeme(lexeme))) => {
|
||||
Transition(TplMeta(
|
||||
tpl,
|
||||
expr,
|
||||
oi_meta.assign_lexeme(ctx.asg_mut(), lexeme),
|
||||
))
|
||||
.incomplete()
|
||||
}
|
||||
(TplMeta(tpl, oi_meta), AirTpl(TplLexeme(lexeme))) => Transition(
|
||||
TplMeta(tpl, oi_meta.assign_lexeme(ctx.asg_mut(), lexeme)),
|
||||
)
|
||||
.incomplete(),
|
||||
|
||||
(TplMeta(tpl, expr, oi_meta), AirBind(BindIdent(name))) => {
|
||||
(TplMeta(tpl, oi_meta), AirBind(BindIdent(name))) => {
|
||||
oi_meta.identify_as_tpl_param(ctx.asg_mut(), tpl.oi(), name);
|
||||
Transition(TplMeta(tpl, expr, oi_meta)).incomplete()
|
||||
Transition(TplMeta(tpl, oi_meta)).incomplete()
|
||||
}
|
||||
|
||||
(TplMeta(..), tok @ AirBind(RefIdent(..))) => {
|
||||
|
@ -273,13 +263,14 @@ impl ParseState for AirTplAggregate {
|
|||
)
|
||||
}
|
||||
|
||||
(Toplevel(tpl, _expr_done), AirTpl(TplEnd(span))) => {
|
||||
(Toplevel(tpl), AirTpl(TplEnd(span))) => {
|
||||
tpl.close(ctx.asg_mut(), span).transition(Ready)
|
||||
}
|
||||
|
||||
(TplExpr(tpl, expr), AirTpl(TplEnd(span))) => {
|
||||
// TODO: duplicated with AirAggregate
|
||||
if expr.is_accepting(ctx) {
|
||||
ctx.pop();
|
||||
tpl.close(ctx.asg_mut(), span).transition(Ready)
|
||||
} else {
|
||||
Transition(TplExpr(tpl, expr))
|
||||
|
@ -287,11 +278,11 @@ impl ParseState for AirTplAggregate {
|
|||
}
|
||||
}
|
||||
|
||||
(Toplevel(tpl, expr_done), AirTpl(TplEndRef(span))) => {
|
||||
(Toplevel(tpl), AirTpl(TplEndRef(span))) => {
|
||||
let oi_target = ctx.expansion_oi().expect("TODO");
|
||||
tpl.oi().expand_into(ctx.asg_mut(), oi_target);
|
||||
|
||||
Transition(Toplevel(tpl.anonymous_reachable(), expr_done))
|
||||
Transition(Toplevel(tpl.anonymous_reachable()))
|
||||
.incomplete()
|
||||
.with_lookahead(AirTpl(TplEnd(span)))
|
||||
}
|
||||
|
@ -306,8 +297,12 @@ impl ParseState for AirTplAggregate {
|
|||
.with_lookahead(AirTpl(TplEnd(span)))
|
||||
}
|
||||
|
||||
(Toplevel(tpl, expr), AirExpr(etok)) => {
|
||||
Self::delegate_expr(ctx, tpl, expr, etok)
|
||||
(Toplevel(tpl), tok @ AirExpr(_)) => {
|
||||
ctx.push(Toplevel(tpl));
|
||||
|
||||
Transition(TplExpr(tpl, AirExprAggregate::new()))
|
||||
.incomplete()
|
||||
.with_lookahead(tok)
|
||||
}
|
||||
|
||||
(TplExpr(tpl, expr), AirExpr(etok)) => {
|
||||
|
@ -355,17 +350,28 @@ impl AirTplAggregate {
|
|||
Self::Ready
|
||||
}
|
||||
|
||||
pub(super) fn active_tpl_oi(&self) -> Option<ObjectIndex<Tpl>> {
|
||||
use AirTplAggregate::*;
|
||||
|
||||
match self {
|
||||
Ready => None,
|
||||
Toplevel(tplst) | TplMeta(tplst, _) | TplExpr(tplst, _) => {
|
||||
Some(tplst.oi())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Delegate to the expression parser [`AirExprAggregate`].
|
||||
fn delegate_expr(
|
||||
asg: &mut <Self as ParseState>::Context,
|
||||
tpl: TplState,
|
||||
expr: AirExprAggregateStoreDangling<Tpl>,
|
||||
etok: impl Into<<AirExprAggregateStoreDangling<Tpl> as ParseState>::Token>,
|
||||
expr: AirExprAggregateStoreDangling,
|
||||
etok: impl Into<<AirExprAggregateStoreDangling as ParseState>::Token>,
|
||||
) -> TransitionResult<Self> {
|
||||
let tok = etok.into();
|
||||
|
||||
expr.parse_token(tok, asg).branch_dead::<Self, _>(
|
||||
|expr, ()| Transition(Self::Toplevel(tpl, expr)).incomplete(),
|
||||
|_, ()| Transition(Self::Toplevel(tpl)).incomplete(),
|
||||
|expr, result, ()| {
|
||||
result
|
||||
.map(ParseStatus::reflexivity)
|
||||
|
|
Loading…
Reference in New Issue