From d195eedacbe4ac90969688304e5aadc9e9ab88c7 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Wed, 19 Oct 2022 10:00:08 -0400 Subject: [PATCH] tamer: nir: Sugared and plain flavors This introduces the concept of sugared NIR and provides the boilerplate for a desugaring pass. The earlier commits dealing with cleaning up the lowering pipeline were to support this work, in particular to ensure that reporting and recovery properly applied to this lowering operation without adding a ton more boilerplate. DEV-13158 --- tamer/src/bin/tamec.rs | 32 ++++-- tamer/src/nir.rs | 88 +++++++++++++++-- tamer/src/nir/desugar.rs | 108 ++++++++++++++++++++ tamer/src/nir/parse.rs | 198 ++++++++++++++++++------------------- tamer/src/xir/parse/ele.rs | 15 +-- 5 files changed, 317 insertions(+), 124 deletions(-) create mode 100644 tamer/src/nir/desugar.rs diff --git a/tamer/src/bin/tamec.rs b/tamer/src/bin/tamec.rs index 2ec56de1..ab345063 100644 --- a/tamer/src/bin/tamec.rs +++ b/tamer/src/bin/tamec.rs @@ -37,7 +37,7 @@ use tamer::{ diagnose::{ AnnotatedSpan, Diagnostic, FsSpanResolver, Reporter, VisualReporter, }, - nir::{XirfToNir, XirfToNirError}, + nir::{DesugarNir, DesugarNirError, SugaredNir, XirfToNir, XirfToNirError}, parse::{ Lower, ParseError, Parsed, ParsedObject, ParsedResult, UnknownToken, }, @@ -135,13 +135,15 @@ fn compile( XirToXirf<64, RefinedText>, _, >::lower::<_, UnrecoverableError>(src, |toks| { - Lower::, XirfToNir, _>::lower(toks, |nir| { - nir.fold(Ok(()), |x, result| match result { - Ok(_) => x, - Err(e) => { - report_err(&e, reporter, &mut ebuf)?; - x - } + Lower::, XirfToNir, _>::lower(toks, |snir| { + Lower::::lower(snir, |nir| { + nir.fold(Ok(()), |x, result| match result { + Ok(_) => x, + Err(e) => { + report_err(&e, reporter, &mut ebuf)?; + x + } + }) }) }) })?; @@ -295,6 +297,7 @@ pub enum RecoverableError { XirParseError(ParseError), XirfParseError(ParseError), NirParseError(ParseError, XirfToNirError>), + DesugarNirError(ParseError), } impl From for UnrecoverableError { @@ -327,12 +330,20 @@ impl From> for RecoverableError { } } -impl From, XirfToNirError>> for RecoverableError { +impl From, XirfToNirError>> + for RecoverableError +{ fn from(e: ParseError, XirfToNirError>) -> Self { Self::NirParseError(e) } } +impl From> for RecoverableError { + fn from(e: ParseError) -> Self { + Self::DesugarNirError(e) + } +} + impl Display for UnrecoverableError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -354,6 +365,7 @@ impl Display for RecoverableError { Self::XirParseError(e) => Display::fmt(e, f), Self::XirfParseError(e) => Display::fmt(e, f), Self::NirParseError(e) => Display::fmt(e, f), + Self::DesugarNirError(e) => Display::fmt(e, f), } } } @@ -375,6 +387,7 @@ impl Error for RecoverableError { Self::XirParseError(e) => Some(e), Self::XirfParseError(e) => Some(e), Self::NirParseError(e) => Some(e), + Self::DesugarNirError(e) => Some(e), } } } @@ -394,6 +407,7 @@ impl Diagnostic for RecoverableError { Self::XirParseError(e) => e.describe(), Self::XirfParseError(e) => e.describe(), Self::NirParseError(e) => e.describe(), + Self::DesugarNirError(e) => e.describe(), } } } diff --git a/tamer/src/nir.rs b/tamer/src/nir.rs index 0455b68f..634f5681 100644 --- a/tamer/src/nir.rs +++ b/tamer/src/nir.rs @@ -1,4 +1,4 @@ -// Normalized source IR +// IR that is "near" the source code. // // Copyright (C) 2014-2022 Ryan Specialty Group, LLC. // @@ -49,9 +49,14 @@ //! The entry point for NIR in the lowering pipeline is exported as //! [`XirfToNir`]. +mod desugar; mod parse; -use std::{convert::Infallible, error::Error, fmt::Display}; +use std::{ + convert::Infallible, + error::Error, + fmt::{Debug, Display}, +}; use crate::{ diagnose::{Annotate, Diagnostic}, @@ -62,22 +67,33 @@ use crate::{ xir::{attr::Attr, fmt::TtXmlAttr, QName}, }; +pub use desugar::{DesugarNir, DesugarNirError}; pub use parse::{ NirParseState as XirfToNir, NirParseStateError_ as XirfToNirError, }; +/// IR that is "near" the source code, +/// without its syntactic sugar. +/// +/// This form contains only primitives that cannot be reasonably represented +/// by other primitives. +/// This is somewhat arbitrary and may change over time, +/// but represents a balance between the level of abstraction of the IR +/// and performance of lowering operations. +/// +/// See [`SugaredNir`] for more information about the sugared form. #[derive(Debug, PartialEq, Eq)] -pub enum Nir { +pub enum PlainNir { Todo, } -impl Token for Nir { +impl Token for PlainNir { fn ir_name() -> &'static str { - "NIR" + "Plain NIR" } - fn span(&self) -> crate::span::Span { - use Nir::*; + fn span(&self) -> Span { + use PlainNir::*; match self { Todo => UNKNOWN_SPAN, @@ -85,11 +101,11 @@ impl Token for Nir { } } -impl Object for Nir {} +impl Object for PlainNir {} -impl Display for Nir { +impl Display for PlainNir { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use Nir::*; + use PlainNir::*; match self { Todo => write!(f, "TODO"), @@ -97,6 +113,58 @@ impl Display for Nir { } } +/// Syntactic sugar atop of [`PlainNir`]. +/// +/// NIR contains various syntax features that serve as mere quality-of-life +/// conveniences for users +/// ("sugar" to sweeten the experience). +/// These features do not add an expressiveness to the language, +/// and are able to be lowered into other primitives without changing +/// its meaning. +/// +/// The process of lowering syntactic sugar into primitives is called +/// "desugaring" and is carried out by the [`DesugarNir`] lowering +/// operation, +/// producing [`PlainNir`]. +/// Tokens that do not require desugaring are already represented as +/// [`PlainNir`] in the [`SugaredNir::Plain`] variant. +#[derive(Debug, PartialEq, Eq)] +pub enum SugaredNir { + Plain(PlainNir), +} + +impl Token for SugaredNir { + fn ir_name() -> &'static str { + "Sugared NIR" + } + + fn span(&self) -> Span { + use SugaredNir::*; + + match self { + Plain(nir) => nir.span(), + } + } +} + +impl Object for SugaredNir {} + +impl Display for SugaredNir { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + use SugaredNir::*; + + match self { + Plain(nir) => Display::fmt(nir, f), + } + } +} + +impl From for SugaredNir { + fn from(nir: PlainNir) -> Self { + Self::Plain(nir) + } +} + // TODO type PkgPath = SymbolId; type PkgTitle = SymbolId; diff --git a/tamer/src/nir/desugar.rs b/tamer/src/nir/desugar.rs new file mode 100644 index 00000000..cab30e62 --- /dev/null +++ b/tamer/src/nir/desugar.rs @@ -0,0 +1,108 @@ +// Normalized (desugared) IR that is "near" the source code. +// +// Copyright (C) 2014-2022 Ryan Specialty Group, LLC. +// +// This file is part of TAME. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Desugaring of [`SugaredNir`] into the normalized [`PlainNir`] form. +//! +//! For more information on the flavors of NIR, +//! see [the parent module](super). + +use std::{error::Error, fmt::Display}; + +use crate::{ + diagnose::{AnnotatedSpan, Diagnostic}, + parse::{NoContext, ParseState, Transition, TransitionResult}, +}; + +use super::{PlainNir, SugaredNir}; + +#[derive(Debug, PartialEq, Eq, Default)] +pub enum DesugarNir { + #[default] + Ready, +} + +impl Display for DesugarNir { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Ready => write!(f, "ready for next token"), + } + } +} + +impl ParseState for DesugarNir { + type Token = SugaredNir; + type Object = PlainNir; + type Error = DesugarNirError; + + fn parse_token( + self, + tok: Self::Token, + _: NoContext, + ) -> TransitionResult { + use SugaredNir::*; + + match tok { + Plain(nir) => Transition(self).ok(nir), + } + } + + fn is_accepting(&self, _: &Self::Context) -> bool { + self == &Self::Ready + } +} + +#[derive(Debug, PartialEq)] +pub enum DesugarNirError {} + +impl Display for DesugarNirError { + fn fmt(&self, _f: &mut std::fmt::Formatter) -> std::fmt::Result { + // No errors yet. + Ok(()) + } +} + +impl Error for DesugarNirError {} + +impl Diagnostic for DesugarNirError { + fn describe(&self) -> Vec { + // No errors yet. + vec![] + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::parse::Parsed; + + type Sut = DesugarNir; + + // Given the simplicity, + // this just really ensures that the parser terminates. + #[test] + fn maps_plain_nir() { + let toks = vec![SugaredNir::Plain(PlainNir::Todo)]; + + use Parsed::*; + assert_eq!( + Ok(vec![Object(PlainNir::Todo)]), + Sut::parse(toks.into_iter()).collect(), + ); + } +} diff --git a/tamer/src/nir/parse.rs b/tamer/src/nir/parse.rs index 1a5ab0d0..f611769d 100644 --- a/tamer/src/nir/parse.rs +++ b/tamer/src/nir/parse.rs @@ -114,7 +114,7 @@ use crate::{ }; ele_parse! { - /// Parser lowering [XIR](crate::xir) into [NIR](crate::nir). + /// Parser lowering [XIR](crate::xir) into [`SugaredNir`]. /// /// TAME's grammar is embedded within XML. /// The outer XML document has its own grammar, @@ -156,13 +156,13 @@ ele_parse! { pub enum NirParseState; type AttrValueError = NirAttrParseError; - type Object = Nir; + type Object = SugaredNir; // Text and template expressions may appear at any point within the // program; // see [`NirParseState`] for more information. [super] { - [text](_sym, _span) => Nir::Todo, + [text](_sym, _span) => PlainNir::Todo, TplKw }; @@ -204,7 +204,7 @@ ele_parse! { // TODO: Is this still needed? // TODO: PkgName type _name: (QN_NAME) => PkgPath, - } => Nir::Todo, + } => PlainNir::Todo, ImportStmt, PkgBodyStmt, @@ -237,7 +237,7 @@ ele_parse! { // TODO: Can this go away now? _name: (QN_NAME?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, ImportStmt, PkgBodyStmt, @@ -251,7 +251,7 @@ ele_parse! { @ { _pkg: (QN_PACKAGE) => PkgPath, _export: (QN_EXPORT?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// A statement that is accepted within the body of a package. @@ -299,7 +299,7 @@ ele_parse! { _dim: (QN_DIM) => NumLiteral, _parent: (QN_PARENT?) => Option, _yields: (QN_YIELDS?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Define an input parameter accepting data from an external system. @@ -315,7 +315,7 @@ ele_parse! { _set: (QN_SET?) => Option, _default: (QN_DEFAULT?) => Option, _sym: (QN_SYM?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Associate static data with an identifier. @@ -340,7 +340,7 @@ ele_parse! { _sym: (QN_SYM?) => Option, // TODO: Misnomer _set: (QN_SET?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, ConstStmtBody, }; @@ -360,7 +360,7 @@ ele_parse! { ConstMatrixRow := QN_SET { @ { _desc: (QN_DESC) => DescLiteral, - } => Nir::Todo, + } => PlainNir::Todo, ConstVectorItem, }; @@ -370,7 +370,7 @@ ele_parse! { @ { _value: (QN_VALUE) => NumLiteral, _desc: (QN_DESC) => DescLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Define a classification and associate it with an identifier. @@ -386,7 +386,7 @@ ele_parse! { _yields: (QN_YIELDS?) => Option, _sym: (QN_SYM?) => Option, _terminate: (QN_TERMINATE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, LogExpr, }; @@ -413,7 +413,7 @@ ele_parse! { // TODO: We'll have private-by-default later. // This is a kludge. _local: (QN_LOCAL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -433,7 +433,7 @@ ele_parse! { _yields: (QN_YIELDS?) => Option, _sym: (QN_SYM?) => Option, _gensym: (QN_GENSYM?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -444,7 +444,7 @@ ele_parse! { _name: (QN_NAME) => TypeIdent, _desc: (QN_DESC) => DescLiteral, _sym: (QN_SYM?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, InnerTypedefStmt, }; @@ -457,7 +457,7 @@ ele_parse! { /// This is used for primitives and allows for core types to be exposed /// to the user. BaseTypeStmt := QN_BASE_TYPE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, }; /// Define an enumerated type. @@ -467,7 +467,7 @@ ele_parse! { EnumStmt := QN_ENUM { @ { _ty: (QN_TYPE) => TypeIdent, - } => Nir::Todo, + } => PlainNir::Todo, ItemEnumStmt, }; @@ -479,13 +479,13 @@ ele_parse! { _name: (QN_NAME) => ConstIdent, _value: (QN_VALUE) => NumLiteral, _desc: (QN_DESC) => DescLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Define a type whose domain is the union of the domains of multiple /// other types. UnionStmt := QN_UNION { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, TypedefStmt, }; @@ -500,7 +500,7 @@ ele_parse! { /// This is being replaced with the `__yield__` template in `core` /// (this statement predates the template system in TAME). YieldStmt := QN_YIELD { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; @@ -522,7 +522,7 @@ ele_parse! { SectionStmt := QN_SECTION { @ { _title: (QN_TITLE) => Title, - } => Nir::Todo, + } => PlainNir::Todo, PkgBodyStmt, }; @@ -533,7 +533,7 @@ ele_parse! { _name: (QN_NAME) => FuncIdent, _desc: (QN_DESC) => DescLiteral, _sym: (QN_SYM?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, FunctionParamStmt, CalcExpr, @@ -548,7 +548,7 @@ ele_parse! { // _TODO: This is a misnomer. _set: (QN_SET?) => Option, _desc: (QN_DESC) => DescLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; @@ -574,7 +574,7 @@ ele_parse! { _value: (QN_VALUE?) => Option, _index: (QN_INDEX?) => Option, _anyof: (QN_ANY_OF?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcPredExpr, }; @@ -584,7 +584,7 @@ ele_parse! { /// This represents an expression that matches when _any_ of its inner /// [`LogExpr`] expressions match. AnyExpr := QN_ANY { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, LogExpr, }; @@ -594,7 +594,7 @@ ele_parse! { /// This represents an expression that matches when _all_ of its inner /// [`LogExpr`] expressions match. AllExpr := QN_ALL { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, LogExpr, }; @@ -661,7 +661,7 @@ ele_parse! { _label: (QN_LABEL?) => Option, _sym: (QN_SYM?) => Option, _dim: (QN_DIM?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, WhenExpr, CalcExpr, @@ -683,7 +683,7 @@ ele_parse! { _dot: (QN_DOT?) => Option, _sym: (QN_SYM?) => Option, _dim: (QN_DIM?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, WhenExpr, CalcExpr, @@ -699,7 +699,7 @@ ele_parse! { QuotientExpr := QN_C_QUOTIENT { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -715,7 +715,7 @@ ele_parse! { /// (respectively), /// but TAMER will be relaxing that restriction. ExptExpr := QN_C_EXPT { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; @@ -730,7 +730,7 @@ ele_parse! { _name: (QN_NAME) => ValueIdent, _index: (QN_INDEX?) => Option, _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, IndexExpr, WhenExpr, @@ -746,7 +746,7 @@ ele_parse! { IndexExpr := QN_C_INDEX { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -765,7 +765,7 @@ ele_parse! { _desc: (QN_DESC?) => Option, // _TODO: deprecate? _ty: (QN_TYPE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, WhenExpr, }; @@ -774,7 +774,7 @@ ele_parse! { CeilExpr := QN_C_CEIL { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -782,7 +782,7 @@ ele_parse! { FloorExpr := QN_C_FLOOR { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -802,7 +802,7 @@ ele_parse! { CasesExpr := QN_C_CASES { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CaseExpr, OtherwiseExpr, @@ -822,7 +822,7 @@ ele_parse! { CaseExpr := QN_C_CASE { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, WhenExpr, CalcExpr, @@ -845,7 +845,7 @@ ele_parse! { OtherwiseExpr := QN_C_OTHERWISE { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -856,7 +856,7 @@ ele_parse! { /// which are vectors of vectors. /// It is not defined for scalars. LengthOfExpr := QN_C_LENGTH_OF { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; @@ -870,7 +870,7 @@ ele_parse! { /// The result of the let expression is the result of the inner /// [`CalcExpr`]. LetExpr := QN_C_LET { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, LetValues, CalcExpr, }; @@ -880,7 +880,7 @@ ele_parse! { /// /// See [`LetExpr`] for more information. LetValues := QN_C_VALUES { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, LetValue, }; @@ -897,7 +897,7 @@ ele_parse! { // Misnomer _set: (QN_SET?) => Option, _desc: (QN_DESC?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -907,7 +907,7 @@ ele_parse! { VectorExpr := QN_C_VECTOR { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -924,9 +924,9 @@ ele_parse! { /// `<`[`c:arg`](QN_C_ARG)` name="α"><`[`c:value-of`](QN_C_VALUE_OF) /// `name="x" />`. ApplyExpr := QN_C_APPLY { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, - [attr](_attr) => Nir::Todo, + [attr](_attr) => PlainNir::Todo, ApplyArg, }; @@ -939,7 +939,7 @@ ele_parse! { ApplyArg := QN_C_ARG { @ { _name: (QN_NAME) => ParamIdent, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -954,9 +954,9 @@ ele_parse! { /// allowing for concise recursion in terms of only what has changed /// in that recursive step. RecurseExpr := QN_C_RECURSE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, - [attr](_attr) => Nir::Todo, + [attr](_attr) => PlainNir::Todo, ApplyArg, }; @@ -967,7 +967,7 @@ ele_parse! { /// This terminology originates from Lisp. /// It is equivalent to an `unshift` operation. ConsExpr := QN_C_CONS { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; @@ -977,7 +977,7 @@ ele_parse! { CarExpr := QN_C_CAR { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -989,7 +989,7 @@ ele_parse! { CdrExpr := QN_C_CDR { @ { _label: (QN_LABEL?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcExpr, }; @@ -1011,7 +1011,7 @@ ele_parse! { _name: (QN_NAME) => ValueIdent, _index: (QN_INDEX?) => Option, _value: (QN_VALUE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, CalcPredExpr, }; @@ -1031,37 +1031,37 @@ ele_parse! { /// Equality predicate (=). EqCalcPredExpr := QN_C_EQ { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; /// Non-equality predicate (≠). NeCalcPredExpr := QN_C_NE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; /// Less-than predicate (<). LtCalcPredExpr := QN_C_LT { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; /// Greater-than predicate (>). GtCalcPredExpr := QN_C_GT { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; /// Less-than or equality predicate (≤). LteCalcPredExpr := QN_C_LTE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; /// Greater-than or equality predicate (≥). GteCalcPredExpr := QN_C_GTE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, CalcExpr, }; @@ -1088,7 +1088,7 @@ ele_parse! { _xmlns: (QN_XMLNS) => Literal, _xmlnslv: (QN_XMLNS_LV) => Literal, _src: (QN_SRC) => PkgPath, - } => Nir::Todo, + } => PlainNir::Todo, MapPkgImportStmt, MapImportStmt, @@ -1106,7 +1106,7 @@ ele_parse! { @ { _xmlns: (QN_XMLNS) => Literal, _xmlnslv: (QN_XMLNS_LV) => Literal, - } => Nir::Todo, + } => PlainNir::Todo, MapPkgImportStmt, MapImportStmt, @@ -1122,7 +1122,7 @@ ele_parse! { @ { _package: (QN_PACKAGE) => PkgPath, _export: (QN_EXPORT?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Import a map package. @@ -1133,7 +1133,7 @@ ele_parse! { MapImportStmt := QN_IMPORT { @ { _path: (QN_PATH) => PkgPath, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Define the value of a key in the destination. @@ -1149,7 +1149,7 @@ ele_parse! { _scalar: (QN_SCALAR?) => Option, _override: (QN_OVERRIDE?) => Option, _novalidate: (QN_NOVALIDATE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Map a value into a key of the destination. @@ -1168,7 +1168,7 @@ ele_parse! { _scalar: (QN_SCALAR?) => Option, _override: (QN_OVERRIDE?) => Option, _novalidate: (QN_NOVALIDATE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, MapStmtBody, }; @@ -1183,7 +1183,7 @@ ele_parse! { _default: (QN_DEFAULT?) => Option, _scalar: (QN_SCALAR?) => Option, _novalidate: (QN_NOVALIDATE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, MapTranslateStmt, }; @@ -1193,7 +1193,7 @@ ele_parse! { @ { _key: (QN_KEY) => StringLiteral, _value: (QN_VALUE) => NumLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Yield a vector of values where each item corresponds to the @@ -1203,7 +1203,7 @@ ele_parse! { /// since the result is a vector, /// not a set. MapSetStmt := QN_SET { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, MapSetBody, }; @@ -1215,7 +1215,7 @@ ele_parse! { MapConstStmt := QN_CONST { @ { _value: (QN_VALUE) => StringLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Transform a value using some function. @@ -1227,7 +1227,7 @@ ele_parse! { MapTransformStmt := QN_TRANSFORM { @ { _method: (QN_METHOD) => MapTransformLiteral, - } => Nir::Todo, + } => PlainNir::Todo, MapStmtBody, }; @@ -1259,7 +1259,7 @@ ele_parse! { _name: (QN_NAME) => PkgPath, _pkg: (QN_PACKAGE) => PkgPath, - } => Nir::Todo, + } => PlainNir::Todo, ExpandFunctionStmt, DisplayStmt, @@ -1276,7 +1276,7 @@ ele_parse! { ExpandFunctionStmt := QN_EXPAND_FUNCTION { @ { _name: (QN_NAME) => FuncIdent, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Render a simplified, human-readable display of the calculation, @@ -1284,7 +1284,7 @@ ele_parse! { DisplayStmt := QN_DISPLAY { @ { _name: (QN_NAME) => ValueIdent, - } => Nir::Todo, + } => PlainNir::Todo, }; @@ -1377,7 +1377,7 @@ ele_parse! { @ { _name: (QN_NAME) => TplName, _desc: (QN_DESC) => DescLiteral, - } => Nir::Todo, + } => PlainNir::Todo, TplHeading, AnyStmtOrExpr, @@ -1402,7 +1402,7 @@ ele_parse! { @ { _name: (QN_NAME) => TplParamIdent, _desc: (QN_DESC) => DescLiteral, - } => Nir::Todo, + } => PlainNir::Todo, TplParamDefault, }; @@ -1435,7 +1435,7 @@ ele_parse! { TplText := QN_TEXT { @ { _unique: (QN_UNIQUE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Default the param to the value of another template param, @@ -1458,7 +1458,7 @@ ele_parse! { _rmunderscore: (QN_RMUNDERSCORE?) => Option, _identifier: (QN_IDENTIFIER?) => Option, _snake: (QN_SNAKE?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Inherit a default value from a metavalue. @@ -1473,7 +1473,7 @@ ele_parse! { TplParamInherit := QN_PARAM_INHERIT { @ { _meta: (QN_META) => TplMetaIdent, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Sum a numeric value with a numeric template parameter. @@ -1484,7 +1484,7 @@ ele_parse! { @ { _name: (QN_NAME) => TplParamIdent, _value: (QN_VALUE) => NumLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Look up the [`@yields`](QN_YIELDS) of a [`ClassifyStmt`]. @@ -1505,7 +1505,7 @@ ele_parse! { TplParamClassToYields := QN_PARAM_CLASS_TO_YIELDS { @ { _name: (QN_NAME) => ClassIdent, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Given a numeric literal, @@ -1550,7 +1550,7 @@ ele_parse! { @ { _name: (QN_NAME) => TypeIdent, _value: (QN_VALUE) => NumLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Look up an attribute from the symbol table for a given identifier. @@ -1560,7 +1560,7 @@ ele_parse! { _value: (QN_VALUE) => SymbolTableKey, _prefix: (QN_PREFIX?) => Option, _ignore_missing: (QN_IGNORE_MISSING?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Keywords that trigger template expansion. @@ -1603,7 +1603,7 @@ ele_parse! { DynNode := QN_DYN_NODE { @ { _name: (QN_NAME) => DynNodeLiteral, - } => Nir::Todo, + } => PlainNir::Todo, // But we can at least restrict it for now by ensuring that it's // used only to contain expressions. @@ -1619,7 +1619,7 @@ ele_parse! { /// See also [`WarningKw`] to provide a message to the user as /// compiler output without failing compilation. ErrorKw := QN_ERROR { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, // In addition to text that is globally permitted. TplParamValue, @@ -1635,7 +1635,7 @@ ele_parse! { /// you should consider using [`ErrorKw`] whenever possible to /// ensure that problems are immediately resolved. WarningKw := QN_WARNING { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, // In addition to text that is globally permitted. TplParamValue, @@ -1657,7 +1657,7 @@ ele_parse! { /// but this is still needed to support dynamic template application /// (templates whose names are derived from other template inputs). ApplyTemplate := QN_APPLY_TEMPLATE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, // TODO }; @@ -1670,12 +1670,12 @@ ele_parse! { /// template argument. /// See [`ApplyTemplate`] for more information. TplApplyShort := NS_T { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, // Streaming attribute parsing; // this takes precedence over any attribute parsing above // (which is used only for emitting the opening object). - [attr](_attr) => Nir::Todo, + [attr](_attr) => PlainNir::Todo, // Template bodies depend on context, // so we have to just accept everything and defer to a future @@ -1695,7 +1695,7 @@ ele_parse! { /// and have the unique ability to perform symbol table /// introspection using [`InlineTemplateSymSet`]. InlineTemplate := QN_INLINE_TEMPLATE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, InlineTemplateForEach, AnyStmtOrExpr, @@ -1710,7 +1710,7 @@ ele_parse! { /// each with the respective [`InlineTemplateArgs`] set as its /// arguments. InlineTemplateForEach := QN_FOR_EACH { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, InlineTemplateArgs, }; @@ -1727,10 +1727,10 @@ ele_parse! { /// /// See also parent [`InlineTemplateForEach`]. InlineTemplateArgSet := QN_SET { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, // Streaming attribute parsing. - [attr](_attr) => Nir::Todo, + [attr](_attr) => PlainNir::Todo, // TODO: REMOVE ME // (bug in `ele_parse!` requiring at least one NT in this @@ -1755,7 +1755,7 @@ ele_parse! { _name_prefix: (QN_NAME_PREFIX?) => Option, _type: (QN_TYPE?) => Option, // TODO: Look at XSL sources for others - } => Nir::Todo, + } => PlainNir::Todo, }; /// Perform template expansion on each successive child node in order, @@ -1785,7 +1785,7 @@ ele_parse! { /// The concept originates from TeX's `\expandafter`, `\edef`, and /// related macros. ExpandSequence := QN_EXPAND_SEQUENCE { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, AnyStmtOrExpr, }; @@ -1795,7 +1795,7 @@ ele_parse! { /// implementation of [`ExpandSequence`]; /// see that NT for more information. ExpandGroup := QN_EXPAND_GROUP { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, AnyStmtOrExpr, }; @@ -1805,7 +1805,7 @@ ele_parse! { /// template system from expanding its body beyond a certain point, /// which is sometimes needed for template-producing templates. ExpandBarrier := QN_EXPAND_BARRIER { - @ {} => Nir::Todo, + @ {} => PlainNir::Todo, AnyStmtOrExpr, }; @@ -1818,7 +1818,7 @@ ele_parse! { TplParamCopy := QN_PARAM_COPY { @ { _name: (QN_NAME) => TplParamIdent, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Define a metavalue at this point in the expansion environment. @@ -1829,7 +1829,7 @@ ele_parse! { @ { _name: (QN_NAME) => TplParamIdent, _value: (QN_VALUE) => StringLiteral, - } => Nir::Todo, + } => PlainNir::Todo, }; /// Conditionally expand the body if the provided predicate matches. @@ -1843,7 +1843,7 @@ ele_parse! { _lte: (QN_LTE?) => Option, _prefix: (QN_PREFIX?) => Option, _suffix: (QN_SUFFIX?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, AnyStmtOrExpr, }; @@ -1863,7 +1863,7 @@ ele_parse! { _lte: (QN_LTE?) => Option, _prefix: (QN_PREFIX?) => Option, _suffix: (QN_SUFFIX?) => Option, - } => Nir::Todo, + } => PlainNir::Todo, AnyStmtOrExpr, }; diff --git a/tamer/src/xir/parse/ele.rs b/tamer/src/xir/parse/ele.rs index fdea0b06..8bcb743e 100644 --- a/tamer/src/xir/parse/ele.rs +++ b/tamer/src/xir/parse/ele.rs @@ -582,7 +582,7 @@ macro_rules! ele_parse { impl std::fmt::Display for $nt { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Self(st) => st.fmt(f), + Self(st) => std::fmt::Display::fmt(st, f), } } } @@ -636,7 +636,7 @@ macro_rules! ele_parse { $( // Used only to match on `[attr]`. let [<_ $attr_stream_binding>] = (); - return transition.ok($attrmap); + return transition.ok(<$objty>::from($attrmap)); )? // If the `[attr]` special form was _not_ @@ -693,7 +693,10 @@ macro_rules! ele_parse { ( st @ Attrs(..), XirfToken::Attr($attr_stream_binding), - ) => Transition(Self(st)).ok($attr_stream_map), + ) => { + Transition(Self(st)) + .ok(<$objty>::from($attr_stream_map)) + }, // Override the aggregate attribute parser // delegation by forcing the below match to become @@ -748,7 +751,7 @@ macro_rules! ele_parse { let $open_span = sa.element_span(); )? - $attrmap + <$objty>::from($attrmap) }, }; @@ -1013,7 +1016,7 @@ macro_rules! ele_parse { impl std::fmt::Display for $nt { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Self(st) => st.fmt(f), + Self(st) => std::fmt::Display::fmt(st, f), } } } @@ -1321,7 +1324,7 @@ macro_rules! ele_parse { _, ) ) if st.can_preempt_node() => { - Transition(st).ok($text_map) + Transition(st).ok(<$objty>::from($text_map)) }, )?