tamer: asg::air::ir: {ExprRef=>RefIdent}
This generalizes the IR, and relates the duals: identifying and referencing. DEV-13708main
parent
e2714ce73f
commit
d99a8efbaf
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue