tamer: asg::air: Errors for rooting_ci() TODOs
This eliminates the TODOs that existed when looking for an OI for rooting an identifier. The change to `rooting_ci` is ridiculous, but I want to get other things done before I jump down the rabbit hole of generalizing that (indexing local identifiers). Though I have an approach in mind. DEV-13708main
parent
a33d0c4ea5
commit
e3d60750a9
|
@ -164,10 +164,10 @@ impl ParseState for AirAggregate {
|
|||
|
||||
// TODO: We don't support package ids yet
|
||||
(st @ Toplevel(..), AirBind(BindIdent(id))) => {
|
||||
Transition(st).err(AsgError::InvalidExprBindContext(id))
|
||||
Transition(st).err(AsgError::InvalidBindContext(id))
|
||||
}
|
||||
(st @ Toplevel(..), AirBind(RefIdent(id))) => {
|
||||
Transition(st).err(AsgError::InvalidExprRefContext(id))
|
||||
Transition(st).err(AsgError::InvalidRefContext(id))
|
||||
}
|
||||
|
||||
// Note: We unfortunately can't match on `AirExpr | AirBind`
|
||||
|
@ -385,16 +385,20 @@ impl AirAggregateCtx {
|
|||
}
|
||||
}
|
||||
|
||||
/// The active container (binding context) for [`Ident`]s.
|
||||
/// The active container (rooting context) for [`Ident`]s.
|
||||
///
|
||||
/// The integer value returned represents the stack offset at which the
|
||||
/// rooting index was found,
|
||||
/// with `0` representing the package.
|
||||
///
|
||||
/// A value of [`None`] indicates that no bindings are permitted in the
|
||||
/// current context.
|
||||
fn rooting_oi(&self) -> Option<ObjectIndexTo<Ident>> {
|
||||
fn rooting_oi(&self) -> Option<(usize, ObjectIndexTo<Ident>)> {
|
||||
let Self(_, stack, _) = self;
|
||||
|
||||
stack.iter().rev().find_map(|st| match st {
|
||||
stack.iter().enumerate().rev().find_map(|(i, st)| match st {
|
||||
AirAggregate::Empty => None,
|
||||
AirAggregate::Toplevel(pkg_oi) => Some((*pkg_oi).into()),
|
||||
AirAggregate::Toplevel(pkg_oi) => Some((i, (*pkg_oi).into())),
|
||||
|
||||
// Expressions never serve as roots for identifiers;
|
||||
// this will always fall through to the parent context.
|
||||
|
@ -408,7 +412,7 @@ impl AirAggregateCtx {
|
|||
// Templates must therefore serve as containers for identifiers
|
||||
// bound therein.
|
||||
AirAggregate::PkgTpl(tplst) => {
|
||||
tplst.active_tpl_oi().map(Into::into)
|
||||
tplst.active_tpl_oi().map(|oi| (i, oi.into()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -479,16 +483,19 @@ impl AirAggregateCtx {
|
|||
/// indexing.
|
||||
///
|
||||
/// TODO: Generalize this.
|
||||
fn defines(&mut self, name: SPair) -> ObjectIndex<Ident> {
|
||||
let oi_root = self.rooting_oi().expect("TODO");
|
||||
let Self(asg, stack, _) = self;
|
||||
fn defines(&mut self, name: SPair) -> Result<ObjectIndex<Ident>, AsgError> {
|
||||
let (stacki, oi_root) = self
|
||||
.rooting_oi()
|
||||
.ok_or(AsgError::InvalidBindContext(name))?;
|
||||
|
||||
match stack.len() {
|
||||
1 => asg
|
||||
let asg = self.asg_mut();
|
||||
|
||||
Ok(match stacki {
|
||||
0 => asg
|
||||
.lookup_global_or_missing(name)
|
||||
.add_edge_from(asg, oi_root, None),
|
||||
_ => oi_root.declare_local(asg, name),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,12 +123,14 @@ impl ParseState for AirExprAggregate {
|
|||
}
|
||||
|
||||
(BuildingExpr(es, oi), AirBind(BindIdent(id))) => {
|
||||
let oi_ident = ctx.defines(id);
|
||||
let result = ctx.defines(id).and_then(|oi_ident| {
|
||||
oi_ident.bind_definition(ctx.asg_mut(), id, oi)
|
||||
});
|
||||
|
||||
// It is important that we do not mark this expression as
|
||||
// reachable unless we successfully bind the identifier.
|
||||
match oi_ident.bind_definition(ctx.asg_mut(), id, oi) {
|
||||
Ok(_) => {
|
||||
match result {
|
||||
Ok(oi_ident) => {
|
||||
Transition(BuildingExpr(es.reachable_by(oi_ident), oi))
|
||||
.incomplete()
|
||||
}
|
||||
|
|
|
@ -506,7 +506,7 @@ fn expr_bind_to_empty() {
|
|||
// since it's likely that a bind token was issued too late,
|
||||
// rather than trying to interpret this as being back in a
|
||||
// package context and binding to the package.
|
||||
Err(ParseError::StateError(AsgError::InvalidExprBindContext(
|
||||
Err(ParseError::StateError(AsgError::InvalidBindContext(
|
||||
id_noexpr_a
|
||||
))),
|
||||
|
||||
|
@ -516,7 +516,7 @@ fn expr_bind_to_empty() {
|
|||
Ok(Parsed::Incomplete), // ExprEnd
|
||||
|
||||
// Another error after a successful expression.
|
||||
Err(ParseError::StateError(AsgError::InvalidExprBindContext(
|
||||
Err(ParseError::StateError(AsgError::InvalidBindContext(
|
||||
id_noexpr_b
|
||||
))),
|
||||
// RECOVERY
|
||||
|
@ -853,7 +853,7 @@ fn expr_ref_outside_of_expr_context() {
|
|||
Ok(Parsed::Incomplete), // ExprEnd
|
||||
|
||||
// Now we're past the header and in expression parsing mode.
|
||||
Err(ParseError::StateError(AsgError::InvalidExprRefContext(
|
||||
Err(ParseError::StateError(AsgError::InvalidRefContext(
|
||||
id_foo
|
||||
))),
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ use super::{
|
|||
AirAggregate, AirAggregateCtx,
|
||||
};
|
||||
use crate::{
|
||||
asg::graph::object::{Meta, ObjectIndexRelTo},
|
||||
asg::graph::object::Meta,
|
||||
diagnose::Annotate,
|
||||
diagnostic_todo,
|
||||
fmt::{DisplayWrapper, TtQuote},
|
||||
|
@ -182,16 +182,13 @@ impl ParseState for AirTplAggregate {
|
|||
"nested tpl open"
|
||||
),
|
||||
|
||||
(Toplevel(tpl), AirBind(BindIdent(id))) => {
|
||||
let oi_root = ctx.rooting_oi().expect("TODO");
|
||||
let asg = ctx.asg_mut();
|
||||
|
||||
asg.lookup_global_or_missing(id)
|
||||
.bind_definition(asg, id, tpl.oi())
|
||||
.map(|oi_ident| oi_root.defines(asg, oi_ident))
|
||||
.map(|_| ())
|
||||
.transition(Toplevel(tpl.identify(id)))
|
||||
}
|
||||
(Toplevel(tpl), AirBind(BindIdent(id))) => ctx
|
||||
.defines(id)
|
||||
.and_then(|oi_ident| {
|
||||
oi_ident.bind_definition(ctx.asg_mut(), id, tpl.oi())
|
||||
})
|
||||
.map(|_| ())
|
||||
.transition(Toplevel(tpl.identify(id))),
|
||||
|
||||
(Toplevel(tpl), AirBind(RefIdent(id))) => {
|
||||
tpl.oi().apply_named_tpl(ctx.asg_mut(), id);
|
||||
|
|
|
@ -102,18 +102,18 @@ pub enum AsgError {
|
|||
/// delimiter.
|
||||
UnbalancedTpl(Span),
|
||||
|
||||
/// Attempted to bind the an identifier to an expression while not in an
|
||||
/// expression context.
|
||||
/// Attempted to bind an identifier to an object while not in a context
|
||||
/// that can receive an identifier binding.
|
||||
///
|
||||
/// Note that the user may encounter an error from a higher-level IR
|
||||
/// instead of this one.
|
||||
InvalidExprBindContext(SPair),
|
||||
InvalidBindContext(SPair),
|
||||
|
||||
/// Attempted to reference an identifier as part of an expression while
|
||||
/// not in an expression context.
|
||||
/// Attempted to reference an identifier while not in a context that can
|
||||
/// receive an identifier reference.
|
||||
///
|
||||
/// Ideally this situation is syntactically invalid in a source IR.
|
||||
InvalidExprRefContext(SPair),
|
||||
InvalidRefContext(SPair),
|
||||
}
|
||||
|
||||
impl Display for AsgError {
|
||||
|
@ -140,10 +140,10 @@ impl Display for AsgError {
|
|||
),
|
||||
UnbalancedExpr(_) => write!(f, "unbalanced expression"),
|
||||
UnbalancedTpl(_) => write!(f, "unbalanced template definition"),
|
||||
InvalidExprBindContext(_) => {
|
||||
InvalidBindContext(_) => {
|
||||
write!(f, "invalid expression identifier binding context")
|
||||
}
|
||||
InvalidExprRefContext(ident) => {
|
||||
InvalidRefContext(ident) => {
|
||||
write!(
|
||||
f,
|
||||
"invalid context for expression identifier {}",
|
||||
|
@ -243,7 +243,7 @@ impl Diagnostic for AsgError {
|
|||
vec![span.error("there is no open template to close here")]
|
||||
}
|
||||
|
||||
InvalidExprBindContext(span) => vec![
|
||||
InvalidBindContext(span) => vec![
|
||||
span.error(
|
||||
"there is no active expression to bind this identifier to",
|
||||
),
|
||||
|
@ -253,7 +253,7 @@ impl Diagnostic for AsgError {
|
|||
),
|
||||
],
|
||||
|
||||
InvalidExprRefContext(ident) => vec![ident.error(
|
||||
InvalidRefContext(ident) => vec![ident.error(
|
||||
"cannot reference the value of an expression from outside \
|
||||
of an expression context",
|
||||
)],
|
||||
|
|
|
@ -697,7 +697,8 @@ impl Asg {
|
|||
|| diagnostic_opaque_ident_desc(ident),
|
||||
|| {
|
||||
format!(
|
||||
"opaque identifier: {} has no object binding",
|
||||
"identifier was not expected to be opaque: \
|
||||
{} has no object binding",
|
||||
TtQuote::wrap(ident),
|
||||
)
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue