From 0e42788dcc108801bb53a34e2510bbd3bb42956a Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Sat, 11 Mar 2023 00:40:54 -0500 Subject: [PATCH] tamer: asg::air: Restrict AirTplAggregate token domain to new AirTemplatable This removes special cases, but it does complicate the parent `AirAggregate` parser. A pattern of delegation is forming, though abstracting it may be an interesting challenge, given Rust's limitation on macro invocations as match arms. But, I think I can manage by generating the entire match using a macro with a match-compatible syntax, augmenting where needed...maybe. This'll be messy. ...but if I can write the nightmare that is `ele_parse!`, I'm sure I can manage this. I just prefer to avoid complex macros unless I really need them. DEV-13708 --- tamer/src/asg/air.rs | 31 +++++++++++++++++++++++++------ tamer/src/asg/air/ir.rs | 13 +++++++++++++ tamer/src/asg/air/tpl.rs | 33 ++++++++++++--------------------- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/tamer/src/asg/air.rs b/tamer/src/asg/air.rs index 3f3eb26c..260d7f36 100644 --- a/tamer/src/asg/air.rs +++ b/tamer/src/asg/air.rs @@ -187,10 +187,19 @@ impl ParseState for AirAggregate { Self::delegate_expr(asg, oi_pkg, expr, etok) } - // Templates can contain just about anything, - // so completely hand over parsing when we're in template mode. - (PkgTpl(oi_pkg, stored_expr, tplst), tok) => { - Self::delegate_tpl(asg, oi_pkg, stored_expr, tplst, tok.into()) + // Template parsing. + (PkgTpl(oi_pkg, stored_expr, tplst), AirExpr(ttok)) => { + Self::delegate_tpl(asg, oi_pkg, stored_expr, tplst, ttok) + } + (PkgTpl(oi_pkg, stored_expr, tplst), AirBind(ttok)) => { + Self::delegate_tpl(asg, oi_pkg, stored_expr, tplst, ttok) + } + (PkgTpl(oi_pkg, stored_expr, tplst), AirTpl(ttok)) => { + Self::delegate_tpl(asg, oi_pkg, stored_expr, tplst, ttok) + } + + (PkgTpl(..), AirPkg(PkgOpen(..))) => { + todo!("templates cannot contain packages") } (Empty, AirTpl(TplClose(..))) => { @@ -213,6 +222,16 @@ impl ParseState for AirAggregate { } } + (PkgTpl(oi_pkg, stored_expr, tplst), AirPkg(PkgClose(span))) => { + match tplst.is_accepting(asg) { + true => Transition(PkgExpr(oi_pkg, stored_expr)) + .incomplete() + .with_lookahead(AirPkg(PkgClose(span))), + false => Transition(PkgTpl(oi_pkg, stored_expr, tplst)) + .err(AsgError::InvalidPkgCloseContext(span)), + } + } + (Empty, tok @ (AirExpr(..) | AirBind(..) | AirTpl(TplOpen(_)))) => { Transition(Empty).err(AsgError::PkgExpected(tok.span())) } @@ -287,9 +306,9 @@ impl AirAggregate { oi_pkg: ObjectIndex, stored_expr: AirExprAggregateReachable, tplst: AirTplAggregate, - tok: Air, + ttok: impl Into<::Token>, ) -> TransitionResult { - tplst.parse_token(tok, asg).branch_dead::( + tplst.parse_token(ttok.into(), asg).branch_dead::( |_, stored_expr| { Transition(Self::PkgExpr(oi_pkg, stored_expr)).incomplete() }, diff --git a/tamer/src/asg/air/ir.rs b/tamer/src/asg/air/ir.rs index 5b5b928c..b8bd609d 100644 --- a/tamer/src/asg/air/ir.rs +++ b/tamer/src/asg/air/ir.rs @@ -334,6 +334,7 @@ macro_rules! sum_ir { // subtypes. $( $(#[$sumattr])* + #[allow(clippy::enum_variant_names)] // intentional consistency #[derive(Debug, PartialEq)] $sumvis enum $sumsub { $( @@ -637,4 +638,16 @@ sum_ir! { /// This is the primary token set when parsing packages, /// since most everything in TAMER is an expression. pub sum enum AirBindableExpr = AirExpr | AirBind; + + /// Tokens that may be used to define or apply templates. + pub sum enum AirTemplatable = AirExpr | AirBind | AirTpl; +} + +impl From for AirTemplatable { + fn from(expr: AirBindableExpr) -> Self { + match expr { + AirBindableExpr::AirExpr(x) => Self::AirExpr(x), + AirBindableExpr::AirBind(x) => Self::AirBind(x), + } + } } diff --git a/tamer/src/asg/air/tpl.rs b/tamer/src/asg/air/tpl.rs index 60108e6b..e9b991e2 100644 --- a/tamer/src/asg/air/tpl.rs +++ b/tamer/src/asg/air/tpl.rs @@ -27,7 +27,8 @@ use super::{ Asg, AsgError, ObjectIndex, }, expr::AirExprAggregateStoreDangling, - Air, AirExprAggregate, + ir::AirTemplatable, + AirExprAggregate, }; use crate::{ fmt::{DisplayWrapper, TtQuote}, @@ -40,9 +41,9 @@ use crate::{ /// /// - Metadata about the template, /// including its parameters; and -/// - A collection of [`Air`] tokens representing the body of the -/// template that will be expanded into the application site when the -/// template is applied. +/// - A collection of [`AirTemplatable`] tokens representing the body of +/// the template that will be expanded into the application site when +/// the template is applied. /// /// This contains an embedded [`AirExprAggregate`] parser for handling /// expressions just the same as [`super::AirAggregate`] does with @@ -98,7 +99,7 @@ impl Display for AirTplAggregate { } impl ParseState for AirTplAggregate { - type Token = Air; + type Token = AirTemplatable; type Object = (); type Error = AsgError; type Context = Asg; @@ -108,12 +109,11 @@ impl ParseState for AirTplAggregate { tok: Self::Token, asg: &mut Self::Context, ) -> TransitionResult { - use super::ir::{AirBind::*, AirSubsets::*, AirTodo::*, AirTpl::*}; + use super::ir::{AirBind::*, AirTpl::*}; + use AirTemplatable::*; use AirTplAggregate::*; - match (self, tok.into()) { - (st, AirTodo(Todo(_))) => Transition(st).incomplete(), - + match (self, tok) { (Ready(oi_pkg), AirTpl(TplOpen(span))) => { let oi_tpl = asg.create(Tpl::new(span)); @@ -161,14 +161,6 @@ impl ParseState for AirTplAggregate { } } - (Toplevel(..) | TplExpr(..), AirPkg(_)) => { - todo!("template cannot define packages") - } - - (Toplevel(..) | TplExpr(..), AirIdent(_)) => { - todo!("linker token cannot be used in templates") - } - ( Toplevel(oi_pkg, oi_tpl, expr, name) | TplExpr(oi_pkg, oi_tpl, expr, name), @@ -187,10 +179,9 @@ impl ParseState for AirTplAggregate { Transition(st).err(AsgError::UnbalancedTpl(span)) } - ( - st @ Ready(..), - tok @ (AirPkg(..) | AirExpr(..) | AirBind(..) | AirIdent(..)), - ) => Transition(st).dead(tok.into()), + (st @ Ready(..), tok @ (AirExpr(..) | AirBind(..))) => { + Transition(st).dead(tok) + } } }