tamer: asg::air::tpl: Distinct, generalized root and targets
Previously, `AirTplAggregate` worked only in a `Pkg` context, being able to root `Tpl` `Ident`s in `Pkg` and expand only into `Pkg`. This still does the same, but generalizes to allow for different roots and expansion targets. This will be utilized to parse nested templates. DEV-13708main
parent
e1c8e371d5
commit
fc569f7551
|
@ -80,7 +80,7 @@ pub enum AirAggregate {
|
||||||
PkgTpl(
|
PkgTpl(
|
||||||
ObjectIndex<Pkg>,
|
ObjectIndex<Pkg>,
|
||||||
AirExprAggregateReachable<Pkg>,
|
AirExprAggregateReachable<Pkg>,
|
||||||
AirTplAggregate,
|
AirTplAggregate<Pkg>,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ impl ParseState for AirAggregate {
|
||||||
) => Transition(PkgTpl(
|
) => Transition(PkgTpl(
|
||||||
oi_pkg,
|
oi_pkg,
|
||||||
expr,
|
expr,
|
||||||
AirTplAggregate::new_in_pkg(oi_pkg),
|
AirTplAggregate::new(oi_pkg, oi_pkg),
|
||||||
))
|
))
|
||||||
.incomplete()
|
.incomplete()
|
||||||
.with_lookahead(tok),
|
.with_lookahead(tok),
|
||||||
|
@ -305,8 +305,8 @@ impl AirAggregate {
|
||||||
asg: &mut <Self as ParseState>::Context,
|
asg: &mut <Self as ParseState>::Context,
|
||||||
oi_pkg: ObjectIndex<Pkg>,
|
oi_pkg: ObjectIndex<Pkg>,
|
||||||
stored_expr: AirExprAggregateReachable<Pkg>,
|
stored_expr: AirExprAggregateReachable<Pkg>,
|
||||||
tplst: AirTplAggregate,
|
tplst: AirTplAggregate<Pkg>,
|
||||||
ttok: impl Into<<AirTplAggregate as ParseState>::Token>,
|
ttok: impl Into<<AirTplAggregate<Pkg> as ParseState>::Token>,
|
||||||
) -> TransitionResult<Self> {
|
) -> TransitionResult<Self> {
|
||||||
tplst.parse_token(ttok.into(), asg).branch_dead::<Self, _>(
|
tplst.parse_token(ttok.into(), asg).branch_dead::<Self, _>(
|
||||||
|_, stored_expr| {
|
|_, stored_expr| {
|
||||||
|
|
|
@ -22,16 +22,16 @@
|
||||||
//! See the [parent module](super) for more information.
|
//! See the [parent module](super) for more information.
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
super::{
|
super::{graph::object::Tpl, Asg, AsgError, ObjectIndex},
|
||||||
graph::object::{Pkg, Tpl},
|
|
||||||
Asg, AsgError, ObjectIndex,
|
|
||||||
},
|
|
||||||
expr::AirExprAggregateStoreDangling,
|
expr::AirExprAggregateStoreDangling,
|
||||||
ir::AirTemplatable,
|
ir::AirTemplatable,
|
||||||
AirExprAggregate,
|
AirExprAggregate,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
asg::graph::object::Meta,
|
asg::{
|
||||||
|
graph::object::{Meta, ObjectRelTo},
|
||||||
|
Ident,
|
||||||
|
},
|
||||||
diagnose::Annotate,
|
diagnose::Annotate,
|
||||||
diagnostic_todo,
|
diagnostic_todo,
|
||||||
fmt::{DisplayWrapper, TtQuote},
|
fmt::{DisplayWrapper, TtQuote},
|
||||||
|
@ -53,7 +53,10 @@ use crate::{
|
||||||
/// expressions just the same as [`super::AirAggregate`] does with
|
/// expressions just the same as [`super::AirAggregate`] does with
|
||||||
/// packages.
|
/// packages.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum AirTplAggregate {
|
pub enum AirTplAggregate<OR, OT = OR>
|
||||||
|
where
|
||||||
|
Self: TplEnvCtxPair<OR, OT>,
|
||||||
|
{
|
||||||
/// Ready for a template,
|
/// Ready for a template,
|
||||||
/// defined as part of the given package.
|
/// defined as part of the given package.
|
||||||
///
|
///
|
||||||
|
@ -62,7 +65,7 @@ pub enum AirTplAggregate {
|
||||||
/// AIR has no restrictions on when template header tokens are
|
/// AIR has no restrictions on when template header tokens are
|
||||||
/// provided,
|
/// provided,
|
||||||
/// which simplifies AIR generation.
|
/// which simplifies AIR generation.
|
||||||
Ready(ObjectIndex<Pkg>),
|
Ready(TplEnvCtx<OR, OT>),
|
||||||
|
|
||||||
/// Toplevel template context.
|
/// Toplevel template context.
|
||||||
///
|
///
|
||||||
|
@ -71,14 +74,14 @@ pub enum AirTplAggregate {
|
||||||
/// applying to the template itself,
|
/// applying to the template itself,
|
||||||
/// or creating an object directly owned by the template.
|
/// or creating an object directly owned by the template.
|
||||||
Toplevel(
|
Toplevel(
|
||||||
ObjectIndex<Pkg>,
|
TplEnvCtx<OR, OT>,
|
||||||
TplState,
|
TplState,
|
||||||
AirExprAggregateStoreDangling<Tpl>,
|
AirExprAggregateStoreDangling<Tpl>,
|
||||||
),
|
),
|
||||||
|
|
||||||
/// Defining a template metavariable.
|
/// Defining a template metavariable.
|
||||||
TplMeta(
|
TplMeta(
|
||||||
ObjectIndex<Pkg>,
|
TplEnvCtx<OR, OT>,
|
||||||
TplState,
|
TplState,
|
||||||
AirExprAggregateStoreDangling<Tpl>,
|
AirExprAggregateStoreDangling<Tpl>,
|
||||||
ObjectIndex<Meta>,
|
ObjectIndex<Meta>,
|
||||||
|
@ -86,13 +89,16 @@ pub enum AirTplAggregate {
|
||||||
|
|
||||||
/// Aggregating tokens into a template.
|
/// Aggregating tokens into a template.
|
||||||
TplExpr(
|
TplExpr(
|
||||||
ObjectIndex<Pkg>,
|
TplEnvCtx<OR, OT>,
|
||||||
TplState,
|
TplState,
|
||||||
AirExprAggregateStoreDangling<Tpl>,
|
AirExprAggregateStoreDangling<Tpl>,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for AirTplAggregate {
|
impl<OR, OT> Display for AirTplAggregate<OR, OT>
|
||||||
|
where
|
||||||
|
Self: TplEnvCtxPair<OR, OT>,
|
||||||
|
{
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Ready(_) => write!(f, "ready for template definition"),
|
Self::Ready(_) => write!(f, "ready for template definition"),
|
||||||
|
@ -108,6 +114,60 @@ impl Display for AirTplAggregate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Environment context for template application.
|
||||||
|
///
|
||||||
|
/// The _root_ `OR` represents a container for [`Ident`]s to named templates
|
||||||
|
/// produced by [`AirTplAggregate`].
|
||||||
|
///
|
||||||
|
/// The _expansion target_ `OT` is where template applications will expand
|
||||||
|
/// into when referenced.
|
||||||
|
/// Note that templates defined _within_ a template will receive a different
|
||||||
|
/// expansion target,
|
||||||
|
/// determined by [`AirTplAggregate``].
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct TplEnvCtx<OR, OT>(ObjectIndex<OR>, ObjectIndex<OT>)
|
||||||
|
where
|
||||||
|
Self: TplEnvCtxPair<OR, OT>;
|
||||||
|
|
||||||
|
// At the time of writing (2023-03),
|
||||||
|
// deriving these macros places `Clone`/`Copy` trait bounds on each of
|
||||||
|
// `OR` and `OT`,
|
||||||
|
// which is nonsense.
|
||||||
|
impl<OR, OT> Clone for TplEnvCtx<OR, OT>
|
||||||
|
where
|
||||||
|
Self: TplEnvCtxPair<OR, OT>,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<OR, OT> Copy for TplEnvCtx<OR, OT> where Self: TplEnvCtxPair<OR, OT> {}
|
||||||
|
|
||||||
|
impl<OR, OT> TplEnvCtx<OR, OT>
|
||||||
|
where
|
||||||
|
Self: TplEnvCtxPair<OR, OT>,
|
||||||
|
{
|
||||||
|
pub fn defines(self, asg: &mut Asg, oi: ObjectIndex<Ident>) -> Self {
|
||||||
|
match self {
|
||||||
|
Self(oi_root, oi_target) => {
|
||||||
|
Self(oi_root.defines(asg, oi), oi_target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn oi_target(&self) -> ObjectIndex<OT> {
|
||||||
|
match self {
|
||||||
|
Self(_, oi_target) => *oi_target,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// More concisely represent trait bounds for [`TplEnvCtx`].
|
||||||
|
pub trait TplEnvCtxPair<OR, OT> = Sized
|
||||||
|
where
|
||||||
|
OR: ObjectRelTo<Ident>,
|
||||||
|
OT: ObjectRelTo<Tpl>;
|
||||||
|
|
||||||
/// The current reachability status of the template.
|
/// The current reachability status of the template.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum TplState {
|
pub enum TplState {
|
||||||
|
@ -177,7 +237,10 @@ impl Display for TplState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseState for AirTplAggregate {
|
impl<OR, OT> ParseState for AirTplAggregate<OR, OT>
|
||||||
|
where
|
||||||
|
Self: TplEnvCtxPair<OR, OT>,
|
||||||
|
{
|
||||||
type Token = AirTemplatable;
|
type Token = AirTemplatable;
|
||||||
type Object = ();
|
type Object = ();
|
||||||
type Error = AsgError;
|
type Error = AsgError;
|
||||||
|
@ -193,11 +256,11 @@ impl ParseState for AirTplAggregate {
|
||||||
use AirTplAggregate::*;
|
use AirTplAggregate::*;
|
||||||
|
|
||||||
match (self, tok) {
|
match (self, tok) {
|
||||||
(Ready(oi_pkg), AirTpl(TplStart(span))) => {
|
(Ready(ois), AirTpl(TplStart(span))) => {
|
||||||
let oi_tpl = asg.create(Tpl::new(span));
|
let oi_tpl = asg.create(Tpl::new(span));
|
||||||
|
|
||||||
Transition(Toplevel(
|
Transition(Toplevel(
|
||||||
oi_pkg,
|
ois,
|
||||||
TplState::Dangling(oi_tpl),
|
TplState::Dangling(oi_tpl),
|
||||||
AirExprAggregate::new_in(oi_tpl),
|
AirExprAggregate::new_in(oi_tpl),
|
||||||
))
|
))
|
||||||
|
@ -209,44 +272,40 @@ impl ParseState for AirTplAggregate {
|
||||||
"nested tpl open"
|
"nested tpl open"
|
||||||
),
|
),
|
||||||
|
|
||||||
(Toplevel(oi_pkg, tpl, expr), AirBind(BindIdent(id))) => asg
|
(Toplevel(ois, tpl, expr), AirBind(BindIdent(id))) => asg
|
||||||
.lookup_global_or_missing(id)
|
.lookup_global_or_missing(id)
|
||||||
.bind_definition(asg, id, tpl.oi())
|
.bind_definition(asg, id, tpl.oi())
|
||||||
.map(|oi_ident| oi_pkg.defines(asg, oi_ident))
|
.map(|oi_ident| ois.defines(asg, oi_ident))
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.transition(Toplevel(oi_pkg, tpl.identify(id), expr)),
|
.transition(Toplevel(ois, tpl.identify(id), expr)),
|
||||||
|
|
||||||
(Toplevel(oi_pkg, tpl, expr), AirBind(RefIdent(id))) => {
|
(Toplevel(ois, tpl, expr), AirBind(RefIdent(id))) => {
|
||||||
tpl.oi().apply_named_tpl(asg, id);
|
tpl.oi().apply_named_tpl(asg, id);
|
||||||
Transition(Toplevel(oi_pkg, tpl, expr)).incomplete()
|
Transition(Toplevel(ois, tpl, expr)).incomplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
(Toplevel(oi_pkg, tpl, expr), AirTpl(TplMetaStart(span))) => {
|
(Toplevel(ois, tpl, expr), AirTpl(TplMetaStart(span))) => {
|
||||||
let oi_meta = asg.create(Meta::new_required(span));
|
let oi_meta = asg.create(Meta::new_required(span));
|
||||||
Transition(TplMeta(oi_pkg, tpl, expr, oi_meta)).incomplete()
|
Transition(TplMeta(ois, tpl, expr, oi_meta)).incomplete()
|
||||||
}
|
}
|
||||||
(
|
(TplMeta(ois, tpl, expr, oi_meta), AirTpl(TplMetaEnd(cspan))) => {
|
||||||
TplMeta(oi_pkg, tpl, expr, oi_meta),
|
|
||||||
AirTpl(TplMetaEnd(cspan)),
|
|
||||||
) => {
|
|
||||||
oi_meta.close(asg, cspan);
|
oi_meta.close(asg, cspan);
|
||||||
Transition(Toplevel(oi_pkg, tpl, expr)).incomplete()
|
Transition(Toplevel(ois, tpl, expr)).incomplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(TplMeta(ois, tpl, expr, oi_meta), AirTpl(TplLexeme(lexeme))) => {
|
||||||
TplMeta(oi_pkg, tpl, expr, oi_meta),
|
Transition(TplMeta(
|
||||||
AirTpl(TplLexeme(lexeme)),
|
ois,
|
||||||
) => Transition(TplMeta(
|
|
||||||
oi_pkg,
|
|
||||||
tpl,
|
tpl,
|
||||||
expr,
|
expr,
|
||||||
oi_meta.assign_lexeme(asg, lexeme),
|
oi_meta.assign_lexeme(asg, lexeme),
|
||||||
))
|
))
|
||||||
.incomplete(),
|
.incomplete()
|
||||||
|
}
|
||||||
|
|
||||||
(TplMeta(oi_pkg, tpl, expr, oi_meta), AirBind(BindIdent(name))) => {
|
(TplMeta(ois, tpl, expr, oi_meta), AirBind(BindIdent(name))) => {
|
||||||
oi_meta.identify_as_tpl_param(asg, tpl.oi(), name);
|
oi_meta.identify_as_tpl_param(asg, tpl.oi(), name);
|
||||||
Transition(TplMeta(oi_pkg, tpl, expr, oi_meta)).incomplete()
|
Transition(TplMeta(ois, tpl, expr, oi_meta)).incomplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
(TplMeta(..), tok @ AirBind(RefIdent(..))) => {
|
(TplMeta(..), tok @ AirBind(RefIdent(..))) => {
|
||||||
|
@ -287,51 +346,43 @@ impl ParseState for AirTplAggregate {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
(Toplevel(oi_pkg, tpl, _expr_done), AirTpl(TplEnd(span))) => {
|
(Toplevel(ois, tpl, _expr_done), AirTpl(TplEnd(span))) => {
|
||||||
tpl.close(asg, span).transition(Ready(oi_pkg))
|
tpl.close(asg, span).transition(Ready(ois))
|
||||||
}
|
}
|
||||||
|
|
||||||
(TplExpr(oi_pkg, tpl, expr), AirTpl(TplEnd(span))) => {
|
(TplExpr(ois, tpl, expr), AirTpl(TplEnd(span))) => {
|
||||||
// TODO: duplicated with AirAggregate
|
// TODO: duplicated with AirAggregate
|
||||||
if expr.is_accepting(asg) {
|
if expr.is_accepting(asg) {
|
||||||
tpl.close(asg, span).transition(Ready(oi_pkg))
|
tpl.close(asg, span).transition(Ready(ois))
|
||||||
} else {
|
} else {
|
||||||
Transition(TplExpr(oi_pkg, tpl, expr))
|
Transition(TplExpr(ois, tpl, expr))
|
||||||
.err(AsgError::InvalidTplEndContext(span))
|
.err(AsgError::InvalidTplEndContext(span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Toplevel(oi_pkg, tpl, expr_done), AirTpl(TplEndRef(span))) => {
|
(Toplevel(ois, tpl, expr_done), AirTpl(TplEndRef(span))) => {
|
||||||
tpl.oi().expand_into(asg, oi_pkg);
|
tpl.oi().expand_into(asg, ois.oi_target());
|
||||||
|
|
||||||
Transition(Toplevel(
|
Transition(Toplevel(ois, tpl.anonymous_reachable(), expr_done))
|
||||||
oi_pkg,
|
|
||||||
tpl.anonymous_reachable(),
|
|
||||||
expr_done,
|
|
||||||
))
|
|
||||||
.incomplete()
|
.incomplete()
|
||||||
.with_lookahead(AirTpl(TplEnd(span)))
|
.with_lookahead(AirTpl(TplEnd(span)))
|
||||||
}
|
}
|
||||||
|
|
||||||
(TplExpr(oi_pkg, tpl, expr_done), AirTpl(TplEndRef(span))) => {
|
(TplExpr(ois, tpl, expr_done), AirTpl(TplEndRef(span))) => {
|
||||||
tpl.oi().expand_into(asg, oi_pkg);
|
tpl.oi().expand_into(asg, ois.oi_target());
|
||||||
|
|
||||||
Transition(TplExpr(
|
Transition(TplExpr(ois, tpl.anonymous_reachable(), expr_done))
|
||||||
oi_pkg,
|
|
||||||
tpl.anonymous_reachable(),
|
|
||||||
expr_done,
|
|
||||||
))
|
|
||||||
.incomplete()
|
.incomplete()
|
||||||
.with_lookahead(AirTpl(TplEnd(span)))
|
.with_lookahead(AirTpl(TplEnd(span)))
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
Toplevel(oi_pkg, tpl, expr) | TplExpr(oi_pkg, tpl, expr),
|
Toplevel(ois, tpl, expr) | TplExpr(ois, tpl, expr),
|
||||||
AirExpr(etok),
|
AirExpr(etok),
|
||||||
) => Self::delegate_expr(asg, oi_pkg, tpl, expr, etok),
|
) => Self::delegate_expr(asg, ois, tpl, expr, etok),
|
||||||
|
|
||||||
(TplExpr(oi_pkg, tpl, expr), AirBind(etok)) => {
|
(TplExpr(ois, tpl, expr), AirBind(etok)) => {
|
||||||
Self::delegate_expr(asg, oi_pkg, tpl, expr, etok)
|
Self::delegate_expr(asg, ois, tpl, expr, etok)
|
||||||
}
|
}
|
||||||
|
|
||||||
(TplExpr(..), AirTpl(TplStart(span))) => {
|
(TplExpr(..), AirTpl(TplStart(span))) => {
|
||||||
|
@ -366,15 +417,21 @@ impl ParseState for AirTplAggregate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AirTplAggregate {
|
impl<OR, OT> AirTplAggregate<OR, OT>
|
||||||
pub(super) fn new_in_pkg(oi_pkg: ObjectIndex<Pkg>) -> Self {
|
where
|
||||||
Self::Ready(oi_pkg)
|
Self: TplEnvCtxPair<OR, OT>,
|
||||||
|
{
|
||||||
|
pub(super) fn new(
|
||||||
|
oi_root: ObjectIndex<OR>,
|
||||||
|
oi_target: ObjectIndex<OT>,
|
||||||
|
) -> Self {
|
||||||
|
Self::Ready(TplEnvCtx(oi_root, oi_target))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delegate to the expression parser [`AirExprAggregate`].
|
/// Delegate to the expression parser [`AirExprAggregate`].
|
||||||
fn delegate_expr(
|
fn delegate_expr(
|
||||||
asg: &mut <Self as ParseState>::Context,
|
asg: &mut <Self as ParseState>::Context,
|
||||||
oi_pkg: ObjectIndex<Pkg>,
|
ois: TplEnvCtx<OR, OT>,
|
||||||
tpl: TplState,
|
tpl: TplState,
|
||||||
expr: AirExprAggregateStoreDangling<Tpl>,
|
expr: AirExprAggregateStoreDangling<Tpl>,
|
||||||
etok: impl Into<<AirExprAggregateStoreDangling<Tpl> as ParseState>::Token>,
|
etok: impl Into<<AirExprAggregateStoreDangling<Tpl> as ParseState>::Token>,
|
||||||
|
@ -382,13 +439,11 @@ impl AirTplAggregate {
|
||||||
let tok = etok.into();
|
let tok = etok.into();
|
||||||
|
|
||||||
expr.parse_token(tok, asg).branch_dead::<Self, _>(
|
expr.parse_token(tok, asg).branch_dead::<Self, _>(
|
||||||
|expr, ()| {
|
|expr, ()| Transition(Self::Toplevel(ois, tpl, expr)).incomplete(),
|
||||||
Transition(Self::Toplevel(oi_pkg, tpl, expr)).incomplete()
|
|
||||||
},
|
|
||||||
|expr, result, ()| {
|
|expr, result, ()| {
|
||||||
result
|
result
|
||||||
.map(ParseStatus::reflexivity)
|
.map(ParseStatus::reflexivity)
|
||||||
.transition(Self::TplExpr(oi_pkg, tpl, expr))
|
.transition(Self::TplExpr(ois, tpl, expr))
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -715,6 +715,14 @@ impl<O: ObjectKind> ObjectIndex<O> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicate that the given identifier `oi` is defined by this object.
|
||||||
|
pub fn defines(self, asg: &mut Asg, oi: ObjectIndex<Ident>) -> Self
|
||||||
|
where
|
||||||
|
O: ObjectRelTo<Ident>,
|
||||||
|
{
|
||||||
|
self.add_edge_to(asg, oi, None)
|
||||||
|
}
|
||||||
|
|
||||||
/// Attempt to look up a locally bound [`Ident`] via a linear search of
|
/// Attempt to look up a locally bound [`Ident`] via a linear search of
|
||||||
/// `self`'s edges.
|
/// `self`'s edges.
|
||||||
///
|
///
|
||||||
|
|
|
@ -72,11 +72,6 @@ object_rel! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectIndex<Pkg> {
|
impl ObjectIndex<Pkg> {
|
||||||
/// Indicate that the given identifier `oi` is defined in this package.
|
|
||||||
pub fn defines(self, asg: &mut Asg, oi: ObjectIndex<Ident>) -> Self {
|
|
||||||
self.add_edge_to(asg, oi, None)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Complete the definition of a package.
|
/// Complete the definition of a package.
|
||||||
pub fn close(self, asg: &mut Asg, span: Span) -> Self {
|
pub fn close(self, asg: &mut Asg, span: Span) -> Self {
|
||||||
self.map_obj(asg, Pkg::fmap(|open| open.merge(span).unwrap_or(open)))
|
self.map_obj(asg, Pkg::fmap(|open| open.merge(span).unwrap_or(open)))
|
||||||
|
|
Loading…
Reference in New Issue