tamer: asg::air::ir: {ExprRef=>RefIdent}

This generalizes the IR, and relates the duals: identifying and referencing.

DEV-13708
main
Mike Gerwitz 2023-03-06 15:17:02 -05:00
parent e2714ce73f
commit d99a8efbaf
4 changed files with 39 additions and 37 deletions

View File

@ -320,8 +320,8 @@ impl ParseState for AirAggregate {
asg: &mut Self::Context,
) -> crate::parse::TransitionResult<Self> {
use ir::{
AirBind::*, AirExpr::*, AirIdent::*, AirPkg::*, AirSubsets::*,
AirTodo::*, AirTpl::*,
AirBind::*, AirIdent::*, AirPkg::*, AirSubsets::*, AirTodo::*,
AirTpl::*,
};
use AirAggregate::*;
@ -403,14 +403,9 @@ impl ParseState for AirAggregate {
}
}
(
Empty,
AirExpr(ExprOpen(_, span))
| AirExpr(ExprClose(span))
| AirTpl(TplOpen(span))
| AirBind(BindIdent(SPair(_, span)))
| AirExpr(ExprRef(SPair(_, span))),
) => Transition(Empty).err(AsgError::PkgExpected(span)),
(Empty, tok @ (AirExpr(..) | AirBind(..) | AirTpl(TplOpen(_)))) => {
Transition(Empty).err(AsgError::PkgExpected(tok.span()))
}
(Empty, AirIdent(IdentDecl(name, kind, src))) => {
asg.declare(name, kind, src).map(|_| ()).transition(Empty)
@ -605,7 +600,7 @@ impl ParseState for AirExprAggregate {
}
}
(BuildingExpr(oi_pkg, es, oi), AirExpr(ExprRef(ident))) => {
(BuildingExpr(oi_pkg, es, oi), AirBind(RefIdent(ident))) => {
Transition(BuildingExpr(oi_pkg, es, oi.ref_expr(asg, ident)))
.incomplete()
}
@ -614,7 +609,7 @@ impl ParseState for AirExprAggregate {
Transition(st).err(AsgError::InvalidExprBindContext(id))
}
(st @ Ready(..), AirExpr(ExprRef(id))) => {
(st @ Ready(..), AirBind(RefIdent(id))) => {
Transition(st).err(AsgError::InvalidExprRefContext(id))
}

View File

@ -499,25 +499,6 @@ sum_ir! {
span: span,
display: |f| write!(f, "close expression"),
},
/// Reference another expression identified by the given [`SPair`].
///
/// Values can be referenced before they are declared or defined,
/// so the provided identifier need not yet exist.
/// However,
/// the identifier must eventually be bound to an [`Expr`].
///
/// Since all values in TAME are referentially tansparent,
/// the system has flexibility in determining what it should do with a
/// reference.
ExprRef(id: SPair) => {
span: id,
display: |f| write!(
f,
"reference to identifier {}",
TtQuote::wrap(id),
),
},
}
/// Subset of [`Air`] tokens dealing with the binding of identifiers
@ -534,6 +515,22 @@ sum_ir! {
TtQuote::wrap(id),
),
},
/// Reference another object identified by the given [`SPair`].
///
/// Objects can be referenced before they are declared or defined,
/// so the provided identifier need not yet exist.
/// However,
/// the identifier must eventually be bound to an object of
/// the appropriate type depending on context.
RefIdent(id: SPair) => {
span: id,
display: |f| write!(
f,
"reference to identifier {}",
TtQuote::wrap(id),
),
},
}
/// Subset of [`Air`] tokens for declaring and manipulating

View File

@ -1004,7 +1004,7 @@ fn expr_ref_to_ident() {
Air::BindIdent(id_foo),
// Reference to an as-of-yet-undefined id (okay),
// with a different span than `id_bar`.
Air::ExprRef(SPair("bar".into(), S3)),
Air::RefIdent(SPair("bar".into(), S3)),
Air::ExprClose(S4),
//
// Another expression to reference the first
@ -1045,7 +1045,7 @@ fn expr_ref_to_ident() {
// The span of the identifier must be updated with the defining
// `BindIdent`,
// otherwise it'll be the location of the `ExprRef` that originally
// otherwise it'll be the location of the `RefIdent` that originally
// added it as `Missing`.
assert_eq!(ident_bar.span(), id_bar.span());
@ -1055,11 +1055,17 @@ fn expr_ref_to_ident() {
#[test]
fn expr_ref_outside_of_expr_context() {
let id_foo = SPair("foo".into(), S2);
let id_pre = SPair("pre".into(), S2);
let id_foo = SPair("foo".into(), S4);
let toks = vec![
// We need to first bring ourselves out of the context of the
// package header.
Air::ExprOpen(ExprOp::Sum, S1),
Air::BindIdent(id_pre),
Air::ExprClose(S3),
// This will fail since we're not in an expression context.
Air::ExprRef(id_foo),
Air::RefIdent(id_foo),
// RECOVERY: Simply ignore the above.
Air::ExprOpen(ExprOp::Sum, S1),
Air::BindIdent(id_foo),
@ -1071,6 +1077,10 @@ fn expr_ref_outside_of_expr_context() {
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // BindIdent
Ok(Parsed::Incomplete), // ExprClose
// Now we're past the header and in expression parsing mode.
Err(ParseError::StateError(AsgError::InvalidExprRefContext(
id_foo
))),
@ -1104,7 +1114,7 @@ fn idents_share_defining_pkg() {
Air::BindIdent(id_foo),
Air::ExprOpen(ExprOp::Sum, S4),
Air::BindIdent(id_bar),
Air::ExprRef(id_baz),
Air::RefIdent(id_baz),
Air::ExprClose(S7),
Air::ExprClose(S8),
Air::PkgClose(S9),

View File

@ -66,7 +66,7 @@ fn traverses_ontological_tree() {
ExprOpen(ExprOp::Sum, S4),
ExprClose(S5),
ExprRef(SPair(id_b.symbol(), S6)),
RefIdent(SPair(id_b.symbol(), S6)),
ExprClose(S7),
ExprOpen(ExprOp::Sum, S8),