tamer: asg::air::ir::Air: Open/Close => Start/End in token names

See the Air docblock for more information.  I'm introducing new tokens for
the template system, which uses the terms "free" and "closed".  I prefer
open/close for delimiters, as I've expressed elsewhere, but unfortunately it
conflicts too much (and too confusingly) with other standard terminology as
we get more into the formal side of the language.

DEV-13708
main
Mike Gerwitz 2023-03-15 10:59:22 -04:00
parent 0e42788dcc
commit 9e5958d89e
11 changed files with 309 additions and 297 deletions

View File

@ -72,9 +72,9 @@ pub enum AirAggregate {
/// Parser is in template parsing mode.
///
/// All objects encountered until the closing [`Air::TplClose`] will be
/// All objects encountered until the closing [`Air::TplEnd`] will be
/// parented to this template rather than the parent [`Pkg`].
/// See [`Air::TplOpen`] for more information.
/// See [`Air::TplStart`] for more information.
PkgTpl(
ObjectIndex<Pkg>,
AirExprAggregateReachable<Pkg>,
@ -126,24 +126,24 @@ impl ParseState for AirAggregate {
match (self, tok.into()) {
(st, AirTodo(Todo(_))) => Transition(st).incomplete(),
(Empty, AirPkg(PkgOpen(span))) => {
(Empty, AirPkg(PkgStart(span))) => {
let oi_pkg = asg.create(Pkg::new(span)).root(asg);
Transition(Toplevel(oi_pkg, AirExprAggregate::new_in(oi_pkg)))
.incomplete()
}
(Toplevel(oi_pkg, expr), AirPkg(PkgOpen(span))) => {
(Toplevel(oi_pkg, expr), AirPkg(PkgStart(span))) => {
Transition(Toplevel(oi_pkg, expr))
.err(AsgError::NestedPkgOpen(span, oi_pkg.span()))
.err(AsgError::NestedPkgStart(span, oi_pkg.span()))
}
(PkgExpr(oi_pkg, expr), AirPkg(PkgOpen(span))) => {
(PkgExpr(oi_pkg, expr), AirPkg(PkgStart(span))) => {
Transition(PkgExpr(oi_pkg, expr))
.err(AsgError::NestedPkgOpen(span, oi_pkg.span()))
.err(AsgError::NestedPkgStart(span, oi_pkg.span()))
}
// No expression was started.
(Toplevel(oi_pkg, _expr), AirPkg(PkgClose(span))) => {
(Toplevel(oi_pkg, _expr), AirPkg(PkgEnd(span))) => {
oi_pkg.close(asg, span);
Transition(Empty).incomplete()
}
@ -198,19 +198,19 @@ impl ParseState for AirAggregate {
Self::delegate_tpl(asg, oi_pkg, stored_expr, tplst, ttok)
}
(PkgTpl(..), AirPkg(PkgOpen(..))) => {
(PkgTpl(..), AirPkg(PkgStart(..))) => {
todo!("templates cannot contain packages")
}
(Empty, AirTpl(TplClose(..))) => {
todo!("Empty AirTpl::TplClose")
(Empty, AirTpl(TplEnd(..))) => {
todo!("Empty AirTpl::TplEnd")
}
(Empty, AirPkg(PkgClose(span))) => {
Transition(Empty).err(AsgError::InvalidPkgCloseContext(span))
(Empty, AirPkg(PkgEnd(span))) => {
Transition(Empty).err(AsgError::InvalidPkgEndContext(span))
}
(PkgExpr(oi_pkg, expr), AirPkg(PkgClose(span))) => {
(PkgExpr(oi_pkg, expr), AirPkg(PkgEnd(span))) => {
match expr.is_accepting(asg) {
true => {
// TODO: this is duplicated with the above
@ -218,23 +218,24 @@ impl ParseState for AirAggregate {
Transition(Empty).incomplete()
}
false => Transition(PkgExpr(oi_pkg, expr))
.err(AsgError::InvalidPkgCloseContext(span)),
.err(AsgError::InvalidPkgEndContext(span)),
}
}
(PkgTpl(oi_pkg, stored_expr, tplst), AirPkg(PkgClose(span))) => {
(PkgTpl(oi_pkg, stored_expr, tplst), AirPkg(PkgEnd(span))) => {
match tplst.is_accepting(asg) {
true => Transition(PkgExpr(oi_pkg, stored_expr))
.incomplete()
.with_lookahead(AirPkg(PkgClose(span))),
.with_lookahead(AirPkg(PkgEnd(span))),
false => Transition(PkgTpl(oi_pkg, stored_expr, tplst))
.err(AsgError::InvalidPkgCloseContext(span)),
.err(AsgError::InvalidPkgEndContext(span)),
}
}
(Empty, tok @ (AirExpr(..) | AirBind(..) | AirTpl(TplOpen(_)))) => {
Transition(Empty).err(AsgError::PkgExpected(tok.span()))
}
(
Empty,
tok @ (AirExpr(..) | AirBind(..) | AirTpl(TplStart(_))),
) => Transition(Empty).err(AsgError::PkgExpected(tok.span())),
(Empty, AirIdent(IdentDecl(name, kind, src))) => {
asg.declare(name, kind, src).map(|_| ()).transition(Empty)

View File

@ -99,17 +99,17 @@ impl<O: ObjectKind, S: RootStrategy<O>> ParseState for AirExprAggregate<O, S> {
use AirExprAggregate::*;
match (self, tok) {
(Ready(root, es, _), AirExpr(ExprOpen(op, span))) => {
(Ready(root, es, _), AirExpr(ExprStart(op, span))) => {
let oi = asg.create(Expr::new(op, span));
Transition(BuildingExpr(root, es.activate(), oi)).incomplete()
}
(BuildingExpr(root, es, poi), AirExpr(ExprOpen(op, span))) => {
(BuildingExpr(root, es, poi), AirExpr(ExprStart(op, span))) => {
let oi = poi.create_subexpr(asg, Expr::new(op, span));
Transition(BuildingExpr(root, es.push(poi), oi)).incomplete()
}
(BuildingExpr(root, es, oi), AirExpr(ExprClose(end))) => {
(BuildingExpr(root, es, oi), AirExpr(ExprEnd(end))) => {
let _ = oi.map_obj(asg, |expr| {
expr.map(|span| span.merge(end).unwrap_or(span))
});
@ -157,7 +157,7 @@ impl<O: ObjectKind, S: RootStrategy<O>> ParseState for AirExprAggregate<O, S> {
.incomplete()
}
(st @ Ready(..), AirExpr(ExprClose(span))) => {
(st @ Ready(..), AirExpr(ExprEnd(span))) => {
Transition(st).err(AsgError::UnbalancedExpr(span))
}

View File

@ -46,9 +46,9 @@ fn expr_empty_ident() {
let id = SPair("foo".into(), S2);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id),
Air::ExprClose(S3),
Air::ExprEnd(S3),
];
let mut sut = parse_as_pkg_body(toks);
@ -67,18 +67,18 @@ fn expr_without_pkg() {
let toks = vec![
// No package
// (because we're not parsing with `parse_as_pkg_body` below)
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
// RECOVERY
Air::PkgOpen(S2),
Air::PkgClose(S3),
Air::PkgStart(S2),
Air::PkgEnd(S3),
];
assert_eq!(
vec![
Err(ParseError::StateError(AsgError::PkgExpected(S1))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // PkgEnd
],
Sut::parse(toks.into_iter()).collect::<Vec<_>>(),
);
@ -90,28 +90,28 @@ fn close_pkg_mid_expr() {
let id = SPair("foo".into(), S4);
let toks = vec![
Air::PkgOpen(S1),
Air::ExprOpen(ExprOp::Sum, S2),
Air::PkgClose(S3),
Air::PkgStart(S1),
Air::ExprStart(ExprOp::Sum, S2),
Air::PkgEnd(S3),
// RECOVERY: Let's finish the expression first...
Air::BindIdent(id),
Air::ExprClose(S5),
Air::ExprEnd(S5),
// ...and then try to close again.
Air::PkgClose(S6),
Air::PkgEnd(S6),
];
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // ExprOpen
Err(ParseError::StateError(AsgError::InvalidPkgCloseContext(S3))),
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // ExprStart
Err(ParseError::StateError(AsgError::InvalidPkgEndContext(S3))),
// RECOVERY: We should be able to close the package if we just
// finish the expression first,
// demonstrating that recovery properly maintains all state.
Ok(Parsed::Incomplete), // BindIdent
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // ExprEnd
// Successful close here.
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
Sut::parse(toks.into_iter()).collect::<Vec<_>>(),
);
@ -122,29 +122,29 @@ fn open_pkg_mid_expr() {
let id = SPair("foo".into(), S4);
let toks = vec![
Air::PkgOpen(S1),
Air::ExprOpen(ExprOp::Sum, S2),
Air::PkgOpen(S3),
Air::PkgStart(S1),
Air::ExprStart(ExprOp::Sum, S2),
Air::PkgStart(S3),
// RECOVERY: We should still be able to complete successfully.
Air::BindIdent(id),
Air::ExprClose(S5),
Air::ExprEnd(S5),
// Closes the _original_ package.
Air::PkgClose(S6),
Air::PkgEnd(S6),
];
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // ExprOpen
Err(ParseError::StateError(AsgError::NestedPkgOpen(S3, S1))),
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // ExprStart
Err(ParseError::StateError(AsgError::NestedPkgStart(S3, S1))),
// RECOVERY: Ignore the open and continue.
// Of course,
// this means that any identifiers would be defined in a
// different package than was likely intended,
// but at least we'll be able to keep processing.
Ok(Parsed::Incomplete), // BindIdent
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // ExprEnd
Ok(Parsed::Incomplete), // PkgEnd
],
Sut::parse(toks.into_iter()).collect::<Vec<_>>(),
);
@ -156,15 +156,15 @@ fn expr_non_empty_ident_root() {
let id_b = SPair("bar".into(), S2);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
// Identifier while still empty...
Air::BindIdent(id_a),
Air::ExprOpen(ExprOp::Sum, S3),
Air::ExprStart(ExprOp::Sum, S3),
// (note that the inner expression _does not_ have an ident binding)
Air::ExprClose(S4),
Air::ExprEnd(S4),
// ...and an identifier non-empty.
Air::BindIdent(id_b),
Air::ExprClose(S6),
Air::ExprEnd(S6),
];
let mut sut = parse_as_pkg_body(toks);
@ -194,15 +194,15 @@ fn expr_non_empty_bind_only_after() {
let id = SPair("foo".into(), S2);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
// Expression root is still dangling at this point.
Air::ExprOpen(ExprOp::Sum, S2),
Air::ExprClose(S3),
Air::ExprStart(ExprOp::Sum, S2),
Air::ExprEnd(S3),
// We only bind an identifier _after_ we've created the expression,
// which should cause the still-dangling root to become
// reachable.
Air::BindIdent(id),
Air::ExprClose(S5),
Air::ExprEnd(S5),
];
let mut sut = parse_as_pkg_body(toks);
@ -221,10 +221,10 @@ fn expr_non_empty_bind_only_after() {
#[test]
fn expr_dangling_no_subexpr() {
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
// No `BindIdent`,
// so this expression is dangling.
Air::ExprClose(S2),
Air::ExprEnd(S2),
];
// The error span should encompass the entire expression.
@ -232,11 +232,11 @@ fn expr_dangling_no_subexpr() {
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete),
Err(ParseError::StateError(AsgError::DanglingExpr(full_span))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
parse_as_pkg_body(toks).collect::<Vec<_>>(),
);
@ -245,26 +245,26 @@ fn expr_dangling_no_subexpr() {
#[test]
fn expr_dangling_with_subexpr() {
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
// Expression root is still dangling at this point.
Air::ExprOpen(ExprOp::Sum, S2),
Air::ExprClose(S3),
Air::ExprStart(ExprOp::Sum, S2),
Air::ExprEnd(S3),
// Still no ident binding,
// so root should still be dangling.
Air::ExprClose(S4),
Air::ExprEnd(S4),
];
let full_span = S1.merge(S4).unwrap();
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Err(ParseError::StateError(AsgError::DanglingExpr(full_span))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
parse_as_pkg_body(toks).collect::<Vec<_>>(),
);
@ -275,33 +275,33 @@ fn expr_dangling_with_subexpr_ident() {
let id = SPair("foo".into(), S3);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
// Expression root is still dangling at this point.
Air::ExprOpen(ExprOp::Sum, S2),
Air::ExprStart(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::BindIdent(id),
Air::ExprClose(S4),
Air::ExprEnd(S4),
// But the root still has no ident binding,
// and so should still be dangling.
Air::ExprClose(S5),
Air::ExprEnd(S5),
];
let full_span = S1.merge(S5).unwrap();
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Err(ParseError::StateError(AsgError::DanglingExpr(full_span))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
parse_as_pkg_body(toks).collect::<Vec<_>>(),
);
@ -316,12 +316,12 @@ fn expr_reachable_subsequent_dangling() {
let id = SPair("foo".into(), S2);
let toks = vec![
// Reachable
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id),
Air::ExprClose(S3),
Air::ExprEnd(S3),
// Dangling
Air::ExprOpen(ExprOp::Sum, S4),
Air::ExprClose(S5),
Air::ExprStart(ExprOp::Sum, S4),
Air::ExprEnd(S5),
];
// The error span should encompass the entire expression.
@ -330,14 +330,14 @@ fn expr_reachable_subsequent_dangling() {
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Err(ParseError::StateError(AsgError::DanglingExpr(second_span))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
parse_as_pkg_body(toks).collect::<Vec<_>>(),
);
@ -349,12 +349,12 @@ fn recovery_expr_reachable_after_dangling() {
let id = SPair("foo".into(), S4);
let toks = vec![
// Dangling
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprClose(S2),
Air::ExprStart(ExprOp::Sum, S1),
Air::ExprEnd(S2),
// Reachable, after error from dangling.
Air::ExprOpen(ExprOp::Sum, S3),
Air::ExprStart(ExprOp::Sum, S3),
Air::BindIdent(id),
Air::ExprClose(S5),
Air::ExprEnd(S5),
];
// The error span should encompass the entire expression.
@ -364,14 +364,14 @@ fn recovery_expr_reachable_after_dangling() {
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete),
Err(ParseError::StateError(AsgError::DanglingExpr(err_span))),
// RECOVERY: continue at this point with the next expression.
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete),
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
sut.by_ref().collect::<Vec<_>>(),
);
@ -398,30 +398,30 @@ fn expr_close_unbalanced() {
let toks = vec![
// Close before _any_ open.
Air::ExprClose(S1),
Air::ExprEnd(S1),
// Should recover,
// allowing for a normal expr.
Air::ExprOpen(ExprOp::Sum, S2),
Air::ExprStart(ExprOp::Sum, S2),
Air::BindIdent(id),
Air::ExprClose(S4),
Air::ExprEnd(S4),
// And now an extra close _after_ a valid expr.
Air::ExprClose(S5),
Air::ExprEnd(S5),
];
let mut sut = parse_as_pkg_body(toks);
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
Err(ParseError::StateError(AsgError::UnbalancedExpr(S1))),
// RECOVERY
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // ExprStart
Ok(Parsed::Incomplete), // BindIdent
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // ExprEnd
// Another error after a successful expression.
Err(ParseError::StateError(AsgError::UnbalancedExpr(S5))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
sut.by_ref().collect::<Vec<_>>(),
);
@ -445,15 +445,15 @@ fn expr_bind_to_empty() {
// package header,
// otherwise the bind will be interpreted as a bind to the
// package itself.
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id_pre),
Air::ExprClose(S3),
Air::ExprEnd(S3),
// No open expression to bind to.
Air::BindIdent(id_noexpr_a),
// Post-recovery create an expression.
Air::ExprOpen(ExprOp::Sum, S5),
Air::ExprStart(ExprOp::Sum, S5),
Air::BindIdent(id_good),
Air::ExprClose(S7),
Air::ExprEnd(S7),
// Once again we have nothing to bind to.
Air::BindIdent(id_noexpr_b),
];
@ -462,11 +462,11 @@ fn expr_bind_to_empty() {
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
// Just to get out of a package header context
Ok(Parsed::Incomplete), // ExprOpen (pre)
Ok(Parsed::Incomplete), // ExprStart (pre)
Ok(Parsed::Incomplete), // BindIdent (pre)
Ok(Parsed::Incomplete), // ExprClose (pre)
Ok(Parsed::Incomplete), // ExprEnd (pre)
// Now that we've encountered an expression,
// we want an error specific to expression binding,
// since it's likely that a bind token was issued too late,
@ -476,15 +476,15 @@ fn expr_bind_to_empty() {
id_noexpr_a
))),
// RECOVERY
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // ExprStart
Ok(Parsed::Incomplete), // BindIdent
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // ExprEnd
// Another error after a successful expression.
Err(ParseError::StateError(AsgError::InvalidExprBindContext(
id_noexpr_b
))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
sut.by_ref().collect::<Vec<_>>(),
);
@ -511,19 +511,19 @@ fn sibling_subexprs_have_ordered_edges_to_parent() {
let id_root = SPair("root".into(), S1);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
// Identify the root so that it is not dangling.
Air::BindIdent(id_root),
// Sibling A
Air::ExprOpen(ExprOp::Sum, S3),
Air::ExprClose(S4),
Air::ExprStart(ExprOp::Sum, S3),
Air::ExprEnd(S4),
// Sibling B
Air::ExprOpen(ExprOp::Sum, S5),
Air::ExprClose(S6),
Air::ExprStart(ExprOp::Sum, S5),
Air::ExprEnd(S6),
// Sibling C
Air::ExprOpen(ExprOp::Sum, S7),
Air::ExprClose(S8),
Air::ExprClose(S9),
Air::ExprStart(ExprOp::Sum, S7),
Air::ExprEnd(S8),
Air::ExprEnd(S9),
];
let asg = asg_from_toks(toks);
@ -556,14 +556,14 @@ fn nested_subexprs_related_to_relative_parent() {
let id_suba = SPair("suba".into(), S2);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1), // 0
Air::ExprStart(ExprOp::Sum, S1), // 0
Air::BindIdent(id_root),
Air::ExprOpen(ExprOp::Sum, S2), // 1
Air::ExprStart(ExprOp::Sum, S2), // 1
Air::BindIdent(id_suba),
Air::ExprOpen(ExprOp::Sum, S3), // 2
Air::ExprClose(S4),
Air::ExprClose(S5),
Air::ExprClose(S6),
Air::ExprStart(ExprOp::Sum, S3), // 2
Air::ExprEnd(S4),
Air::ExprEnd(S5),
Air::ExprEnd(S6),
];
let asg = asg_from_toks(toks);
@ -592,30 +592,30 @@ fn expr_redefine_ident() {
let id_dup = SPair("foo".into(), S3);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id_first),
Air::ExprOpen(ExprOp::Sum, S3),
Air::ExprStart(ExprOp::Sum, S3),
Air::BindIdent(id_dup),
Air::ExprClose(S4),
Air::ExprClose(S5),
Air::ExprEnd(S4),
Air::ExprEnd(S5),
];
let mut sut = parse_as_pkg_body(toks);
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // ExprStart
Ok(Parsed::Incomplete), // BindIdent (first)
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // ExprStart
Err(ParseError::StateError(AsgError::IdentRedefine(
id_first,
id_dup.span(),
))),
// RECOVERY: Ignore the attempt to redefine and continue.
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // ExprEnd
Ok(Parsed::Incomplete), // ExprEnd
Ok(Parsed::Incomplete), // PkgEnd
],
sut.by_ref().collect::<Vec<_>>(),
);
@ -642,34 +642,34 @@ fn expr_still_dangling_on_redefine() {
let toks = vec![
// First expr (OK)
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id_first),
Air::ExprClose(S3),
Air::ExprEnd(S3),
// Second expr should still dangle due to use of duplicate
// identifier
Air::ExprOpen(ExprOp::Sum, S4),
Air::ExprStart(ExprOp::Sum, S4),
Air::BindIdent(id_dup),
Air::ExprClose(S6),
Air::ExprEnd(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::ExprOpen(ExprOp::Sum, S7),
Air::ExprStart(ExprOp::Sum, S7),
Air::BindIdent(id_dup2), // fail
Air::BindIdent(id_second), // succeed
Air::ExprClose(S10),
Air::ExprEnd(S10),
];
let mut sut = parse_as_pkg_body(toks);
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // ExprStart
Ok(Parsed::Incomplete), // BindIdent (first)
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // ExprEnd
// Beginning of second expression
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // ExprStart
Err(ParseError::StateError(AsgError::IdentRedefine(
id_first,
id_dup.span(),
@ -683,7 +683,7 @@ fn expr_still_dangling_on_redefine() {
// RECOVERY: But we'll continue onto one final expression,
// which we will fail to define but then subsequently define
// successfully.
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // ExprStart
Err(ParseError::StateError(AsgError::IdentRedefine(
id_first,
id_dup2.span(),
@ -691,8 +691,8 @@ fn expr_still_dangling_on_redefine() {
// RECOVERY: Despite the initial failure,
// we can now re-attempt to bind with a unique id.
Ok(Parsed::Incomplete), // BindIdent (second)
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // ExprEnd
Ok(Parsed::Incomplete), // PkgEnd
],
sut.by_ref().collect::<Vec<_>>(),
);
@ -718,20 +718,20 @@ fn expr_ref_to_ident() {
let id_bar = SPair("bar".into(), S6);
let toks = vec![
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id_foo),
// Reference to an as-of-yet-undefined id (okay),
// with a different span than `id_bar`.
Air::RefIdent(SPair("bar".into(), S3)),
Air::ExprClose(S4),
Air::ExprEnd(S4),
//
// Another expression to reference the first
// (we don't handle cyclic references until a topological sort,
// so no point in referencing ourselves;
// it'd work just fine here.)
Air::ExprOpen(ExprOp::Sum, S5),
Air::ExprStart(ExprOp::Sum, S5),
Air::BindIdent(id_bar),
Air::ExprClose(S7),
Air::ExprEnd(S7),
];
let asg = asg_from_toks(toks);
@ -779,34 +779,34 @@ fn expr_ref_outside_of_expr_context() {
let toks = vec![
// We need to first bring ourselves out of the context of the
// package header.
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id_pre),
Air::ExprClose(S3),
Air::ExprEnd(S3),
// This will fail since we're not in an expression context.
Air::RefIdent(id_foo),
// RECOVERY: Simply ignore the above.
Air::ExprOpen(ExprOp::Sum, S1),
Air::ExprStart(ExprOp::Sum, S1),
Air::BindIdent(id_foo),
Air::ExprClose(S3),
Air::ExprEnd(S3),
];
let mut sut = parse_as_pkg_body(toks);
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // ExprStart
Ok(Parsed::Incomplete), // BindIdent
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // ExprEnd
// Now we're past the header and in expression parsing mode.
Err(ParseError::StateError(AsgError::InvalidExprRefContext(
id_foo
))),
// RECOVERY: Proceed as normal
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // ExprStart
Ok(Parsed::Incomplete), // BindIdent
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // ExprEnd
Ok(Parsed::Incomplete), // PkgEnd
],
sut.by_ref().collect::<Vec<_>>(),
);
@ -827,15 +827,15 @@ fn idents_share_defining_pkg() {
// An expression nested within another.
let toks = vec![
Air::PkgOpen(S1),
Air::ExprOpen(ExprOp::Sum, S2),
Air::PkgStart(S1),
Air::ExprStart(ExprOp::Sum, S2),
Air::BindIdent(id_foo),
Air::ExprOpen(ExprOp::Sum, S4),
Air::ExprStart(ExprOp::Sum, S4),
Air::BindIdent(id_bar),
Air::RefIdent(id_baz),
Air::ExprClose(S7),
Air::ExprClose(S8),
Air::PkgClose(S9),
Air::ExprEnd(S7),
Air::ExprEnd(S8),
Air::PkgEnd(S9),
];
let mut sut = Sut::parse(toks.into_iter());

View File

@ -406,6 +406,20 @@ sum_ir! {
/// populating the ASG with the raw data that that will be
/// subsequently analyzed and rewritten.
///
/// Terminology
/// ===========
/// AIR uses the terms _start_ and _end_ to refer to tokens that act as
/// delimiters,
/// which is in contrast to other IRs of this system.
/// This is to avoid confusing terminology conflicts with the term
/// _closed_—an
/// object is _closed_ if it contains no free variables.
/// A variable is _free_ in some object if it has no value.
/// For example,
/// a template is closed iff all of its parameters have been bound to
/// values
/// (have received arguments or have assumed their defaults).
///
/// Implementation Notes
/// ====================
/// [`Air`] is a public token type;
@ -453,13 +467,13 @@ sum_ir! {
/// TODO: The package needs a name,
/// and we'll need to determine how to best represent that relative to
/// the project root and be considerate of symlinks.
PkgOpen(span: Span) => {
PkgStart(span: Span) => {
span: span,
display: |f| write!(f, "open package"),
},
/// Complete processing of the current package.
PkgClose(span: Span) => {
PkgEnd(span: Span) => {
span: span,
display: |f| write!(f, "close package"),
},
@ -486,14 +500,14 @@ sum_ir! {
/// [`Air::BindIdent`].
///
/// Expressions are composed of references to other expressions.
ExprOpen(op: ExprOp, span: Span) => {
ExprStart(op: ExprOp, span: Span) => {
span: span,
display: |f| write!(f, "open {op} expression"),
},
/// Complete the expression atop of the expression stack and pop it from
/// the stack.
ExprClose(span: Span) => {
ExprEnd(span: Span) => {
span: span,
display: |f| write!(f, "close expression"),
},
@ -610,7 +624,7 @@ sum_ir! {
enum AirTpl {
/// Create a new [`Tpl`] on the graph and switch to template parsing.
///
/// Until [`Self::TplClose`] is found,
/// Until [`Self::TplEnd`] is found,
/// all parsed objects will be parented to the [`Tpl`] rather than the
/// parent [`Pkg`].
/// Template parsing also recognizes additional nodes that can appear
@ -618,7 +632,7 @@ sum_ir! {
///
/// The active expression stack will be restored after template
/// parsing has concluded.
TplOpen(span: Span) => {
TplStart(span: Span) => {
span: span,
display: |f| write!(f, "open template"),
},
@ -626,7 +640,7 @@ sum_ir! {
/// Close the active [`Tpl`] and exit template parsing.
///
/// The expression stack will be restored to its prior state.
TplClose(span: Span) => {
TplEnd(span: Span) => {
span: span,
display: |f| write!(f, "close template"),
},

View File

@ -246,7 +246,7 @@ fn ident_root_existing() {
#[test]
fn pkg_is_rooted() {
let toks = vec![Air::PkgOpen(S1), Air::PkgClose(S2)];
let toks = vec![Air::PkgStart(S1), Air::PkgEnd(S2)];
let mut sut = Sut::parse(toks.into_iter());
assert!(sut.all(|x| x.is_ok()));
@ -266,18 +266,18 @@ fn pkg_is_rooted() {
#[test]
fn close_pkg_without_open() {
let toks = vec![
Air::PkgClose(S1),
Air::PkgEnd(S1),
// RECOVERY: Try again.
Air::PkgOpen(S2),
Air::PkgClose(S3),
Air::PkgStart(S2),
Air::PkgEnd(S3),
];
assert_eq!(
vec![
Err(ParseError::StateError(AsgError::InvalidPkgCloseContext(S1))),
Err(ParseError::StateError(AsgError::InvalidPkgEndContext(S1))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // PkgEnd
],
Sut::parse(toks.into_iter()).collect::<Vec<_>>(),
);
@ -286,18 +286,18 @@ fn close_pkg_without_open() {
#[test]
fn nested_open_pkg() {
let toks = vec![
Air::PkgOpen(S1),
Air::PkgOpen(S2),
Air::PkgStart(S1),
Air::PkgStart(S2),
// RECOVERY
Air::PkgClose(S3),
Air::PkgEnd(S3),
];
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Err(ParseError::StateError(AsgError::NestedPkgOpen(S2, S1))),
Ok(Parsed::Incomplete), // PkgStart
Err(ParseError::StateError(AsgError::NestedPkgStart(S2, S1))),
// RECOVERY
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // PkgEnd
],
Sut::parse(toks.into_iter()).collect::<Vec<_>>(),
);
@ -313,9 +313,9 @@ where
use std::iter;
Sut::parse(
iter::once(Air::PkgOpen(S1))
iter::once(Air::PkgStart(S1))
.chain(toks.into_iter())
.chain(iter::once(Air::PkgClose(S1))),
.chain(iter::once(Air::PkgEnd(S1))),
)
}

View File

@ -114,7 +114,7 @@ impl ParseState for AirTplAggregate {
use AirTplAggregate::*;
match (self, tok) {
(Ready(oi_pkg), AirTpl(TplOpen(span))) => {
(Ready(oi_pkg), AirTpl(TplStart(span))) => {
let oi_tpl = asg.create(Tpl::new(span));
Transition(Toplevel(
@ -126,7 +126,7 @@ impl ParseState for AirTplAggregate {
.incomplete()
}
(Toplevel(..), AirTpl(TplOpen(_span))) => todo!("nested tpl open"),
(Toplevel(..), AirTpl(TplStart(_span))) => todo!("nested tpl open"),
(Toplevel(oi_pkg, oi_tpl, expr, _), AirBind(BindIdent(name))) => {
asg.lookup_or_missing(name)
@ -140,15 +140,12 @@ impl ParseState for AirTplAggregate {
todo!("tpl Toplevel RefIdent")
}
(
Toplevel(oi_pkg, oi_tpl, _expr_done, _),
AirTpl(TplClose(span)),
) => {
(Toplevel(oi_pkg, oi_tpl, _expr_done, _), AirTpl(TplEnd(span))) => {
oi_tpl.close(asg, span);
Transition(Ready(oi_pkg)).incomplete()
}
(TplExpr(oi_pkg, oi_tpl, expr, name), AirTpl(TplClose(span))) => {
(TplExpr(oi_pkg, oi_tpl, expr, name), AirTpl(TplEnd(span))) => {
// TODO: duplicated with AirAggregate
match expr.is_accepting(asg) {
true => {
@ -157,7 +154,7 @@ impl ParseState for AirTplAggregate {
Transition(Ready(oi_pkg)).incomplete()
}
false => Transition(TplExpr(oi_pkg, oi_tpl, expr, name))
.err(AsgError::InvalidTplCloseContext(span)),
.err(AsgError::InvalidTplEndContext(span)),
}
}
@ -171,11 +168,11 @@ impl ParseState for AirTplAggregate {
Self::delegate_expr(asg, oi_pkg, oi_tpl, expr, name, etok)
}
(TplExpr(..), AirTpl(TplOpen(_))) => {
(TplExpr(..), AirTpl(TplStart(_))) => {
todo!("nested template (template-generated template)")
}
(st @ Ready(..), AirTpl(TplClose(span))) => {
(st @ Ready(..), AirTpl(TplEnd(span))) => {
Transition(st).err(AsgError::UnbalancedTpl(span))
}

View File

@ -37,12 +37,12 @@ fn tpl_defining_pkg() {
let id_tpl = SPair("_tpl_".into(), S3);
let toks = vec![
Air::PkgOpen(S1),
Air::PkgStart(S1),
// This also tests tpl as a transition away from the package header.
Air::TplOpen(S2),
Air::TplStart(S2),
Air::BindIdent(id_tpl),
Air::TplClose(S4),
Air::PkgClose(S5),
Air::TplEnd(S4),
Air::PkgEnd(S5),
];
let mut sut = Sut::parse(toks.into_iter());
@ -66,18 +66,18 @@ fn tpl_after_expr() {
#[rustfmt::skip]
let toks = vec![
Air::PkgOpen(S1),
Air::PkgStart(S1),
// This expression is incidental to this test;
// it need only parse.
Air::ExprOpen(ExprOp::Sum, S2),
Air::ExprStart(ExprOp::Sum, S2),
Air::BindIdent(id_expr),
Air::ExprClose(S4),
Air::ExprEnd(S4),
// Open after an expression.
Air::TplOpen(S5),
Air::TplStart(S5),
Air::BindIdent(id_tpl),
Air::TplClose(S7),
Air::PkgClose(S8),
Air::TplEnd(S7),
Air::PkgEnd(S8),
];
let mut sut = Sut::parse(toks.into_iter());
@ -105,27 +105,27 @@ fn tpl_within_expr() {
#[rustfmt::skip]
let toks = vec![
Air::PkgOpen(S1),
Air::ExprOpen(ExprOp::Sum, S2),
Air::PkgStart(S1),
Air::ExprStart(ExprOp::Sum, S2),
Air::BindIdent(id_expr),
// Child expression before the template to ensure that the
// context is properly restored after template parsing.
Air::ExprOpen(ExprOp::Sum, S4),
Air::ExprClose(S5),
Air::ExprStart(ExprOp::Sum, S4),
Air::ExprEnd(S5),
// Template _within_ an expression.
// This will not be present in the final expression,
// as if it were hoisted out.
Air::TplOpen(S6),
Air::TplStart(S6),
Air::BindIdent(id_tpl),
Air::TplClose(S8),
Air::TplEnd(S8),
// Child expression _after_ the template for the same reason.
Air::ExprOpen(ExprOp::Sum, S9),
Air::ExprClose(S10),
Air::ExprClose(S11),
Air::PkgClose(S12),
Air::ExprStart(ExprOp::Sum, S9),
Air::ExprEnd(S10),
Air::ExprEnd(S11),
Air::PkgEnd(S12),
];
let mut sut = Sut::parse(toks.into_iter());
@ -159,20 +159,20 @@ fn tpl_within_expr() {
#[test]
fn close_tpl_without_open() {
let toks = vec![
Air::TplClose(S1),
Air::TplEnd(S1),
// RECOVERY: Try again.
Air::TplOpen(S2),
Air::TplClose(S3),
Air::TplStart(S2),
Air::TplEnd(S3),
];
assert_eq!(
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // PkgStart
Err(ParseError::StateError(AsgError::UnbalancedTpl(S1))),
// RECOVERY
Ok(Parsed::Incomplete), // TplOpen
Ok(Parsed::Incomplete), // TplClose
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // TplStart
Ok(Parsed::Incomplete), // TplEnd
Ok(Parsed::Incomplete), // PkgEnd
],
parse_as_pkg_body(toks).collect::<Vec<_>>(),
);
@ -186,17 +186,17 @@ fn tpl_with_reachable_expression() {
#[rustfmt::skip]
let toks = vec![
Air::TplOpen(S1),
Air::TplStart(S1),
Air::BindIdent(id_tpl),
Air::ExprOpen(ExprOp::Sum, S3),
Air::ExprStart(ExprOp::Sum, S3),
Air::BindIdent(id_expr_a),
Air::ExprClose(S5),
Air::ExprEnd(S5),
Air::ExprOpen(ExprOp::Sum, S6),
Air::ExprStart(ExprOp::Sum, S6),
Air::BindIdent(id_expr_b),
Air::ExprClose(S8),
Air::TplClose(S9),
Air::ExprEnd(S8),
Air::TplEnd(S9),
];
let asg = asg_from_toks(toks);
@ -240,17 +240,17 @@ fn tpl_holds_dangling_expressions() {
#[rustfmt::skip]
let toks = vec![
Air::TplOpen(S1),
Air::TplStart(S1),
Air::BindIdent(id_tpl),
// Dangling
Air::ExprOpen(ExprOp::Sum, S3),
Air::ExprClose(S4),
Air::ExprStart(ExprOp::Sum, S3),
Air::ExprEnd(S4),
// Dangling
Air::ExprOpen(ExprOp::Sum, S5),
Air::ExprClose(S6),
Air::TplClose(S7),
Air::ExprStart(ExprOp::Sum, S5),
Air::ExprEnd(S6),
Air::TplEnd(S7),
];
let asg = asg_from_toks(toks);
@ -272,30 +272,30 @@ fn close_tpl_mid_open() {
#[rustfmt::skip]
let toks = vec![
Air::TplOpen(S1),
Air::ExprOpen(ExprOp::Sum, S2),
Air::TplStart(S1),
Air::ExprStart(ExprOp::Sum, S2),
Air::BindIdent(id_expr),
// This is misplaced.
Air::TplClose(S4),
Air::TplEnd(S4),
// RECOVERY: Close the expression and try again.
Air::ExprClose(S5),
Air::TplClose(S6),
Air::ExprEnd(S5),
Air::TplEnd(S6),
];
assert_eq!(
#[rustfmt::skip]
vec![
Ok(Parsed::Incomplete), // PkgOpen
Ok(Parsed::Incomplete), // TplOpen
Ok(Parsed::Incomplete), // ExprOpen
Ok(Parsed::Incomplete), // PkgStart
Ok(Parsed::Incomplete), // TplStart
Ok(Parsed::Incomplete), // ExprStart
Ok(Parsed::Incomplete), // BindIdent
Err(ParseError::StateError(
AsgError::InvalidTplCloseContext(S4))
AsgError::InvalidTplEndContext(S4))
),
// RECOVERY
Ok(Parsed::Incomplete), // ExprClose
Ok(Parsed::Incomplete), // TplClose
Ok(Parsed::Incomplete), // PkgClose
Ok(Parsed::Incomplete), // ExprEnd
Ok(Parsed::Incomplete), // TplEnd
Ok(Parsed::Incomplete), // PkgEnd
],
parse_as_pkg_body(toks).collect::<Vec<_>>(),
);

View File

@ -67,10 +67,10 @@ pub enum AsgError {
/// The first span represents the location of the second package open,
/// and the second span represents the location of the package already
/// being defined.
NestedPkgOpen(Span, Span),
NestedPkgStart(Span, Span),
/// Attempted to close a package when not in a package toplevel context.
InvalidPkgCloseContext(Span),
InvalidPkgEndContext(Span),
/// Attempted to open an expression in an invalid context.
PkgExpected(Span),
@ -111,7 +111,7 @@ pub enum AsgError {
/// Attempted to close a template when not in a template toplevel
/// context.
InvalidTplCloseContext(Span),
InvalidTplEndContext(Span),
}
impl Display for AsgError {
@ -123,8 +123,8 @@ impl Display for AsgError {
IdentRedefine(spair, _) => {
write!(f, "cannot redefine {}", TtQuote::wrap(spair))
}
NestedPkgOpen(_, _) => write!(f, "cannot nest packages"),
InvalidPkgCloseContext(_) => {
NestedPkgStart(_, _) => write!(f, "cannot nest packages"),
InvalidPkgEndContext(_) => {
write!(f, "invalid context for package close",)
}
PkgExpected(_) => write!(f, "expected package definition"),
@ -144,7 +144,7 @@ impl Display for AsgError {
TtQuote::wrap(ident)
)
}
InvalidTplCloseContext(_) => {
InvalidTplEndContext(_) => {
write!(f, "invalid context for template close",)
}
}
@ -188,7 +188,7 @@ impl Diagnostic for AsgError {
.help(" defined and its definition cannot be changed."),
],
NestedPkgOpen(second, first) => vec![
NestedPkgStart(second, first) => vec![
first.note("this package is still being defined"),
second.error("attempted to open another package here"),
second.help(
@ -197,7 +197,7 @@ impl Diagnostic for AsgError {
),
],
InvalidPkgCloseContext(span) => vec![
InvalidPkgEndContext(span) => vec![
span.error("package close was not expected here"),
span.help(
"a package must be closed at the same level of nesting \
@ -244,7 +244,7 @@ impl Diagnostic for AsgError {
of an expression context",
)],
InvalidTplCloseContext(span) => vec![
InvalidTplEndContext(span) => vec![
span.error("template close was not expected here"),
span.help(
"a template must be closed at the same level of nesting \

View File

@ -63,20 +63,20 @@ fn traverses_ontological_tree() {
#[rustfmt::skip]
let toks = vec![
PkgOpen(S1),
ExprOpen(ExprOp::Sum, S2),
PkgStart(S1),
ExprStart(ExprOp::Sum, S2),
BindIdent(id_a),
ExprOpen(ExprOp::Sum, S4),
ExprClose(S5),
ExprStart(ExprOp::Sum, S4),
ExprEnd(S5),
RefIdent(SPair(id_b.symbol(), S6)),
ExprClose(S7),
ExprEnd(S7),
ExprOpen(ExprOp::Sum, S8),
ExprStart(ExprOp::Sum, S8),
BindIdent(id_b),
ExprClose(S10),
PkgClose(S11),
ExprEnd(S10),
PkgEnd(S11),
];
let asg = asg_from_toks(toks);
@ -140,20 +140,20 @@ fn traverses_ontological_tree_tpl_with_sibling_at_increasing_depth() {
#[rustfmt::skip]
let toks = vec![
PkgOpen(S1),
TplOpen(S2),
PkgStart(S1),
TplStart(S2),
BindIdent(id_tpl),
// Dangling
ExprOpen(ExprOp::Sum, S4),
ExprClose(S5),
ExprStart(ExprOp::Sum, S4),
ExprEnd(S5),
// Reachable
ExprOpen(ExprOp::Sum, S6),
ExprStart(ExprOp::Sum, S6),
BindIdent(id_expr),
ExprClose(S8),
TplClose(S9),
PkgClose(S10),
ExprEnd(S8),
TplEnd(S9),
PkgEnd(S10),
];
let asg = asg_from_toks(toks);

View File

@ -68,38 +68,38 @@ impl ParseState for NirToAir {
#[allow(unreachable_code)] // due to wip-nir-to-air
match (self, tok) {
(Ready, Nir::Open(NirEntity::Package, span)) => {
Transition(Ready).ok(Air::PkgOpen(span))
Transition(Ready).ok(Air::PkgStart(span))
}
(Ready, Nir::Close(NirEntity::Package, span)) => {
Transition(Ready).ok(Air::PkgClose(span))
Transition(Ready).ok(Air::PkgEnd(span))
}
(Ready, Nir::Open(NirEntity::Rate | NirEntity::Sum, span)) => {
Transition(Ready).ok(Air::ExprOpen(ExprOp::Sum, span))
Transition(Ready).ok(Air::ExprStart(ExprOp::Sum, span))
}
(Ready, Nir::Open(NirEntity::Product, span)) => {
Transition(Ready).ok(Air::ExprOpen(ExprOp::Product, span))
Transition(Ready).ok(Air::ExprStart(ExprOp::Product, span))
}
(Ready, Nir::Open(NirEntity::Ceil, span)) => {
Transition(Ready).ok(Air::ExprOpen(ExprOp::Ceil, span))
Transition(Ready).ok(Air::ExprStart(ExprOp::Ceil, span))
}
(Ready, Nir::Open(NirEntity::Floor, span)) => {
Transition(Ready).ok(Air::ExprOpen(ExprOp::Floor, span))
Transition(Ready).ok(Air::ExprStart(ExprOp::Floor, span))
}
(Ready, Nir::Open(NirEntity::Classify | NirEntity::All, span)) => {
Transition(Ready).ok(Air::ExprOpen(ExprOp::Conj, span))
Transition(Ready).ok(Air::ExprStart(ExprOp::Conj, span))
}
(Ready, Nir::Open(NirEntity::Any, span)) => {
Transition(Ready).ok(Air::ExprOpen(ExprOp::Disj, span))
Transition(Ready).ok(Air::ExprStart(ExprOp::Disj, span))
}
(Ready, Nir::Open(NirEntity::Tpl, span)) => {
Transition(Ready).ok(Air::TplOpen(span))
Transition(Ready).ok(Air::TplStart(span))
}
(Ready, Nir::Close(NirEntity::Tpl, span)) => {
Transition(Ready).ok(Air::TplClose(span))
Transition(Ready).ok(Air::TplEnd(span))
}
(
@ -115,7 +115,7 @@ impl ParseState for NirToAir {
| NirEntity::Any,
span,
),
) => Transition(Ready).ok(Air::ExprClose(span)),
) => Transition(Ready).ok(Air::ExprEnd(span)),
(Ready, Nir::BindIdent(spair)) => {
Transition(Ready).ok(Air::BindIdent(spair))

View File

@ -32,7 +32,7 @@ fn package_to_pkg() {
];
assert_eq!(
Ok(vec![O(Air::PkgOpen(S1)), O(Air::PkgClose(S2)),]),
Ok(vec![O(Air::PkgStart(S1)), O(Air::PkgEnd(S2)),]),
Sut::parse(toks.into_iter()).collect(),
);
}
@ -49,9 +49,9 @@ fn rate_to_sum_expr() {
assert_eq!(
Ok(vec![
O(Air::ExprOpen(ExprOp::Sum, S1)),
O(Air::ExprStart(ExprOp::Sum, S1)),
O(Air::BindIdent(id)),
O(Air::ExprClose(S3)),
O(Air::ExprEnd(S3)),
]),
Sut::parse(toks.into_iter()).collect(),
);
@ -68,10 +68,10 @@ fn calc_exprs() {
assert_eq!(
Ok(vec![
O(Air::ExprOpen(ExprOp::Sum, S1)),
O(Air::ExprOpen(ExprOp::Product, S2)),
O(Air::ExprClose(S3)),
O(Air::ExprClose(S4)),
O(Air::ExprStart(ExprOp::Sum, S1)),
O(Air::ExprStart(ExprOp::Product, S2)),
O(Air::ExprEnd(S3)),
O(Air::ExprEnd(S4)),
]),
Sut::parse(toks.into_iter()).collect(),
);
@ -89,9 +89,9 @@ fn classify_to_conj_expr() {
assert_eq!(
Ok(vec![
O(Air::ExprOpen(ExprOp::Conj, S1)),
O(Air::ExprStart(ExprOp::Conj, S1)),
O(Air::BindIdent(id)),
O(Air::ExprClose(S3)),
O(Air::ExprEnd(S3)),
]),
Sut::parse(toks.into_iter()).collect(),
);
@ -108,10 +108,10 @@ fn logic_exprs() {
assert_eq!(
Ok(vec![
O(Air::ExprOpen(ExprOp::Conj, S1)),
O(Air::ExprOpen(ExprOp::Disj, S2)),
O(Air::ExprClose(S3)),
O(Air::ExprClose(S4)),
O(Air::ExprStart(ExprOp::Conj, S1)),
O(Air::ExprStart(ExprOp::Disj, S2)),
O(Air::ExprEnd(S3)),
O(Air::ExprEnd(S4)),
]),
Sut::parse(toks.into_iter()).collect(),
);
@ -130,9 +130,9 @@ fn tpl_with_name() {
#[rustfmt::skip]
assert_eq!(
Ok(vec![
O(Air::TplOpen(S1)),
O(Air::TplStart(S1)),
O(Air::BindIdent(name)),
O(Air::TplClose(S3)),
O(Air::TplEnd(S3)),
]),
Sut::parse(toks.into_iter()).collect(),
);