tamer: asg::air::Air: {*Expr=>Expr*}
Makes grouping and code completion easier when they're prefixed. DEV-13597main
parent
ae675a8f29
commit
ee30600f67
|
@ -85,21 +85,21 @@ pub enum Air {
|
|||
/// the expression will be evaluated.
|
||||
/// An expression is associated with a source location,
|
||||
/// but is anonymous unless assigned an identifier using
|
||||
/// [`Air::IdentExpr`].
|
||||
/// [`Air::ExprIdent`].
|
||||
///
|
||||
/// Expressions are composed of references to other expressions.
|
||||
OpenExpr(ExprOp, Span),
|
||||
ExprOpen(ExprOp, Span),
|
||||
|
||||
/// Complete the expression atop of the expression stack and pop it from
|
||||
/// the stack.
|
||||
CloseExpr(Span),
|
||||
ExprClose(Span),
|
||||
|
||||
/// Assign an identifier to the expression atop of the expression stack.
|
||||
///
|
||||
/// An expression may be bound to multiple identifiers,
|
||||
/// but an identifier can only be bound to a single expression.
|
||||
/// Binding an identifier will declare it.
|
||||
IdentExpr(SPair),
|
||||
ExprIdent(SPair),
|
||||
|
||||
/// Declare a resolved identifier.
|
||||
IdentDecl(SPair, IdentKind, Source),
|
||||
|
@ -144,9 +144,9 @@ impl Token for Air {
|
|||
match self {
|
||||
Todo => UNKNOWN_SPAN,
|
||||
|
||||
OpenExpr(_, span) | CloseExpr(span) => *span,
|
||||
ExprOpen(_, span) | ExprClose(span) => *span,
|
||||
|
||||
IdentExpr(spair)
|
||||
ExprIdent(spair)
|
||||
| IdentDecl(spair, _, _)
|
||||
| IdentExternDecl(spair, _, _)
|
||||
| IdentDep(spair, _)
|
||||
|
@ -165,11 +165,11 @@ impl Display for Air {
|
|||
match self {
|
||||
Todo => write!(f, "TODO"),
|
||||
|
||||
OpenExpr(op, _) => write!(f, "open {op} expression"),
|
||||
ExprOpen(op, _) => write!(f, "open {op} expression"),
|
||||
|
||||
CloseExpr(_) => write!(f, "close expression"),
|
||||
ExprClose(_) => write!(f, "close expression"),
|
||||
|
||||
IdentExpr(id) => {
|
||||
ExprIdent(id) => {
|
||||
write!(f, "identify expression as {}", TtQuote::wrap(id))
|
||||
}
|
||||
|
||||
|
@ -439,21 +439,21 @@ impl ParseState for AirAggregate {
|
|||
match (self, tok) {
|
||||
(st, Todo) => Transition(st).incomplete(),
|
||||
|
||||
(Empty(es), OpenExpr(op, span)) => {
|
||||
(Empty(es), ExprOpen(op, span)) => {
|
||||
let oi = asg.create(Expr::new(op, span));
|
||||
Transition(BuildingExpr(es.activate(), oi)).incomplete()
|
||||
}
|
||||
|
||||
(BuildingExpr(es, poi), OpenExpr(op, span)) => {
|
||||
(BuildingExpr(es, poi), ExprOpen(op, span)) => {
|
||||
let oi = poi.create_subexpr(asg, Expr::new(op, span));
|
||||
Transition(BuildingExpr(es.push(poi), oi)).incomplete()
|
||||
}
|
||||
|
||||
(st @ Empty(_), CloseExpr(span)) => {
|
||||
(st @ Empty(_), ExprClose(span)) => {
|
||||
Transition(st).err(AsgError::UnbalancedExpr(span))
|
||||
}
|
||||
|
||||
(BuildingExpr(es, oi), CloseExpr(end)) => {
|
||||
(BuildingExpr(es, oi), ExprClose(end)) => {
|
||||
let start: Span = oi.into();
|
||||
|
||||
let _ = oi.map_obj(asg, |expr| {
|
||||
|
@ -479,11 +479,11 @@ impl ParseState for AirAggregate {
|
|||
}
|
||||
}
|
||||
|
||||
(st @ Empty(_), IdentExpr(ident)) => {
|
||||
(st @ Empty(_), ExprIdent(ident)) => {
|
||||
Transition(st).err(AsgError::InvalidExprBindContext(ident))
|
||||
}
|
||||
|
||||
(BuildingExpr(es, oi), IdentExpr(id)) => {
|
||||
(BuildingExpr(es, oi), ExprIdent(id)) => {
|
||||
let identi = asg.lookup_or_missing(id);
|
||||
|
||||
// It is important that we do not mark this expression as
|
||||
|
|
|
@ -250,9 +250,9 @@ fn expr_empty_ident() {
|
|||
let id = SPair("foo".into(), S2);
|
||||
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::IdentExpr(id),
|
||||
Air::CloseExpr(S3),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
Air::ExprIdent(id),
|
||||
Air::ExprClose(S3),
|
||||
];
|
||||
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
|
@ -272,15 +272,15 @@ fn expr_non_empty_ident_root() {
|
|||
let id_b = SPair("bar".into(), S2);
|
||||
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
// Identifier while still empty...
|
||||
Air::IdentExpr(id_a),
|
||||
Air::OpenExpr(ExprOp::Sum, S3),
|
||||
Air::ExprIdent(id_a),
|
||||
Air::ExprOpen(ExprOp::Sum, S3),
|
||||
// (note that the inner expression _does not_ have an ident binding)
|
||||
Air::CloseExpr(S4),
|
||||
Air::ExprClose(S4),
|
||||
// ...and an identifier non-empty.
|
||||
Air::IdentExpr(id_b),
|
||||
Air::CloseExpr(S6),
|
||||
Air::ExprIdent(id_b),
|
||||
Air::ExprClose(S6),
|
||||
];
|
||||
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
|
@ -304,15 +304,15 @@ fn expr_non_empty_bind_only_after() {
|
|||
let id = SPair("foo".into(), S2);
|
||||
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
// Expression root is still dangling at this point.
|
||||
Air::OpenExpr(ExprOp::Sum, S2),
|
||||
Air::CloseExpr(S3),
|
||||
Air::ExprOpen(ExprOp::Sum, S2),
|
||||
Air::ExprClose(S3),
|
||||
// We only bind an identifier _after_ we've created the expression,
|
||||
// which should cause the still-dangling root to become
|
||||
// reachable.
|
||||
Air::IdentExpr(id),
|
||||
Air::CloseExpr(S5),
|
||||
Air::ExprIdent(id),
|
||||
Air::ExprClose(S5),
|
||||
];
|
||||
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
|
@ -331,10 +331,10 @@ fn expr_non_empty_bind_only_after() {
|
|||
#[test]
|
||||
fn expr_dangling_no_subexpr() {
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
// No `IdentExpr`,
|
||||
// so this expression is dangling.
|
||||
Air::CloseExpr(S2),
|
||||
Air::ExprClose(S2),
|
||||
];
|
||||
|
||||
// The error span should encompass the entire expression.
|
||||
|
@ -352,13 +352,13 @@ fn expr_dangling_no_subexpr() {
|
|||
#[test]
|
||||
fn expr_dangling_with_subexpr() {
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
// Expression root is still dangling at this point.
|
||||
Air::OpenExpr(ExprOp::Sum, S2),
|
||||
Air::CloseExpr(S3),
|
||||
Air::ExprOpen(ExprOp::Sum, S2),
|
||||
Air::ExprClose(S3),
|
||||
// Still no ident binding,
|
||||
// so root should still be dangling.
|
||||
Air::CloseExpr(S4),
|
||||
Air::ExprClose(S4),
|
||||
];
|
||||
|
||||
let full_span = S1.merge(S4).unwrap();
|
||||
|
@ -379,19 +379,19 @@ fn expr_dangling_with_subexpr_ident() {
|
|||
let id = SPair("foo".into(), S3);
|
||||
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
// Expression root is still dangling at this point.
|
||||
Air::OpenExpr(ExprOp::Sum, S2),
|
||||
Air::ExprOpen(ExprOp::Sum, S2),
|
||||
// The _inner_ expression receives an identifier,
|
||||
// but that should have no impact on the dangling status of the
|
||||
// root,
|
||||
// especially given that subexpressions are always reachable
|
||||
// anyway.
|
||||
Air::IdentExpr(id),
|
||||
Air::CloseExpr(S4),
|
||||
Air::ExprIdent(id),
|
||||
Air::ExprClose(S4),
|
||||
// But the root still has no ident binding,
|
||||
// and so should still be dangling.
|
||||
Air::CloseExpr(S5),
|
||||
Air::ExprClose(S5),
|
||||
];
|
||||
|
||||
let full_span = S1.merge(S5).unwrap();
|
||||
|
@ -417,12 +417,12 @@ fn expr_reachable_subsequent_dangling() {
|
|||
let id = SPair("foo".into(), S2);
|
||||
let toks = vec![
|
||||
// Reachable
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::IdentExpr(id),
|
||||
Air::CloseExpr(S3),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
Air::ExprIdent(id),
|
||||
Air::ExprClose(S3),
|
||||
// Dangling
|
||||
Air::OpenExpr(ExprOp::Sum, S4),
|
||||
Air::CloseExpr(S5),
|
||||
Air::ExprOpen(ExprOp::Sum, S4),
|
||||
Air::ExprClose(S5),
|
||||
];
|
||||
|
||||
// The error span should encompass the entire expression.
|
||||
|
@ -447,12 +447,12 @@ fn recovery_expr_reachable_after_dangling() {
|
|||
let id = SPair("foo".into(), S4);
|
||||
let toks = vec![
|
||||
// Dangling
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::CloseExpr(S2),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
Air::ExprClose(S2),
|
||||
// Reachable, after error from dangling.
|
||||
Air::OpenExpr(ExprOp::Sum, S3),
|
||||
Air::IdentExpr(id),
|
||||
Air::CloseExpr(S5),
|
||||
Air::ExprOpen(ExprOp::Sum, S3),
|
||||
Air::ExprIdent(id),
|
||||
Air::ExprClose(S5),
|
||||
];
|
||||
|
||||
// The error span should encompass the entire expression.
|
||||
|
@ -495,14 +495,14 @@ fn expr_close_unbalanced() {
|
|||
|
||||
let toks = vec![
|
||||
// Close before _any_ open.
|
||||
Air::CloseExpr(S1),
|
||||
Air::ExprClose(S1),
|
||||
// Should recover,
|
||||
// allowing for a normal expr.
|
||||
Air::OpenExpr(ExprOp::Sum, S2),
|
||||
Air::IdentExpr(id),
|
||||
Air::CloseExpr(S4),
|
||||
Air::ExprOpen(ExprOp::Sum, S2),
|
||||
Air::ExprIdent(id),
|
||||
Air::ExprClose(S4),
|
||||
// And now an extra close _after_ a valid expr.
|
||||
Air::CloseExpr(S5),
|
||||
Air::ExprClose(S5),
|
||||
];
|
||||
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
|
@ -535,13 +535,13 @@ fn expr_bind_to_empty() {
|
|||
|
||||
let toks = vec![
|
||||
// No open expression to bind to.
|
||||
Air::IdentExpr(id_noexpr_a),
|
||||
Air::ExprIdent(id_noexpr_a),
|
||||
// Post-recovery create an expression.
|
||||
Air::OpenExpr(ExprOp::Sum, S2),
|
||||
Air::IdentExpr(id_good),
|
||||
Air::CloseExpr(S4),
|
||||
Air::ExprOpen(ExprOp::Sum, S2),
|
||||
Air::ExprIdent(id_good),
|
||||
Air::ExprClose(S4),
|
||||
// Once again we have nothing to bind to.
|
||||
Air::IdentExpr(id_noexpr_b),
|
||||
Air::ExprIdent(id_noexpr_b),
|
||||
];
|
||||
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
|
@ -585,19 +585,19 @@ fn sibling_subexprs_have_ordered_edges_to_parent() {
|
|||
let id_root = SPair("root".into(), S1);
|
||||
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
// Identify the root so that it is not dangling.
|
||||
Air::IdentExpr(id_root),
|
||||
Air::ExprIdent(id_root),
|
||||
// Sibling A
|
||||
Air::OpenExpr(ExprOp::Sum, S3),
|
||||
Air::CloseExpr(S4),
|
||||
Air::ExprOpen(ExprOp::Sum, S3),
|
||||
Air::ExprClose(S4),
|
||||
// Sibling B
|
||||
Air::OpenExpr(ExprOp::Sum, S5),
|
||||
Air::CloseExpr(S6),
|
||||
Air::ExprOpen(ExprOp::Sum, S5),
|
||||
Air::ExprClose(S6),
|
||||
// Sibling C
|
||||
Air::OpenExpr(ExprOp::Sum, S7),
|
||||
Air::CloseExpr(S8),
|
||||
Air::CloseExpr(S9),
|
||||
Air::ExprOpen(ExprOp::Sum, S7),
|
||||
Air::ExprClose(S8),
|
||||
Air::ExprClose(S9),
|
||||
];
|
||||
|
||||
let asg = asg_from_toks(toks);
|
||||
|
@ -630,14 +630,14 @@ fn nested_subexprs_related_to_relative_parent() {
|
|||
let id_suba = SPair("suba".into(), S2);
|
||||
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1), // 0
|
||||
Air::IdentExpr(id_root),
|
||||
Air::OpenExpr(ExprOp::Sum, S2), // 1
|
||||
Air::IdentExpr(id_suba),
|
||||
Air::OpenExpr(ExprOp::Sum, S3), // 2
|
||||
Air::CloseExpr(S4),
|
||||
Air::CloseExpr(S5),
|
||||
Air::CloseExpr(S6),
|
||||
Air::ExprOpen(ExprOp::Sum, S1), // 0
|
||||
Air::ExprIdent(id_root),
|
||||
Air::ExprOpen(ExprOp::Sum, S2), // 1
|
||||
Air::ExprIdent(id_suba),
|
||||
Air::ExprOpen(ExprOp::Sum, S3), // 2
|
||||
Air::ExprClose(S4),
|
||||
Air::ExprClose(S5),
|
||||
Air::ExprClose(S6),
|
||||
];
|
||||
|
||||
let asg = asg_from_toks(toks);
|
||||
|
@ -666,12 +666,12 @@ fn expr_redefine_ident() {
|
|||
let id_dup = SPair("foo".into(), S3);
|
||||
|
||||
let toks = vec![
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::IdentExpr(id_first),
|
||||
Air::OpenExpr(ExprOp::Sum, S3),
|
||||
Air::IdentExpr(id_dup),
|
||||
Air::CloseExpr(S4),
|
||||
Air::CloseExpr(S5),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
Air::ExprIdent(id_first),
|
||||
Air::ExprOpen(ExprOp::Sum, S3),
|
||||
Air::ExprIdent(id_dup),
|
||||
Air::ExprClose(S4),
|
||||
Air::ExprClose(S5),
|
||||
];
|
||||
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
|
@ -714,22 +714,22 @@ fn expr_still_dangling_on_redefine() {
|
|||
|
||||
let toks = vec![
|
||||
// First expr (OK)
|
||||
Air::OpenExpr(ExprOp::Sum, S1),
|
||||
Air::IdentExpr(id_first),
|
||||
Air::CloseExpr(S3),
|
||||
Air::ExprOpen(ExprOp::Sum, S1),
|
||||
Air::ExprIdent(id_first),
|
||||
Air::ExprClose(S3),
|
||||
// Second expr should still dangle due to use of duplicate
|
||||
// identifier
|
||||
Air::OpenExpr(ExprOp::Sum, S4),
|
||||
Air::IdentExpr(id_dup),
|
||||
Air::CloseExpr(S6),
|
||||
Air::ExprOpen(ExprOp::Sum, S4),
|
||||
Air::ExprIdent(id_dup),
|
||||
Air::ExprClose(S6),
|
||||
// Third expr will error on redefine but then be successful.
|
||||
// This probably won't happen in practice with TAME's original
|
||||
// source language,
|
||||
// but could happen at e.g. a REPL.
|
||||
Air::OpenExpr(ExprOp::Sum, S7),
|
||||
Air::IdentExpr(id_dup2), // fail
|
||||
Air::IdentExpr(id_second), // succeed
|
||||
Air::CloseExpr(S10),
|
||||
Air::ExprOpen(ExprOp::Sum, S7),
|
||||
Air::ExprIdent(id_dup2), // fail
|
||||
Air::ExprIdent(id_second), // succeed
|
||||
Air::ExprClose(S10),
|
||||
];
|
||||
|
||||
let mut sut = Sut::parse(toks.into_iter());
|
||||
|
|
Loading…
Reference in New Issue