From 24eecaa3fdc831817433f6ba589af94e8a674fd9 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Mon, 23 Jan 2023 16:30:25 -0500 Subject: [PATCH] tamer: nir: Basic rate block translation This commit is what I've been sitting on for testing some of the recent changes; it is a very basic demonstration of lowering all the way down from source XML files into the ASG. This can be run on real files to observe, beyond unit tests, how the system reacts. Once this outputs data from the graph, we'll finally have tamec end-to-end and can just keep filling the gaps. I'm hoping to roll the desugaring process into NirToAir rather than having a separate process as originally planned a couple of months back. This also introduces the `wip-nir-to-air` feature flag. Currently, interpolation will cause a `Nir::BindIdent` to be emitted in blocks that aren't yet emitting NIR, and so results in an invalid parse. DEV-13159 --- tamer/Cargo.toml | 6 ++++++ tamer/src/nir.rs | 11 ++++++++++ tamer/src/nir/air.rs | 37 +++++++++++++++++++++++++++++--- tamer/src/nir/air/test.rs | 45 +++++++++++++++++++++++++++++++++++++++ tamer/src/nir/parse.rs | 7 +++--- tamer/src/xir.rs | 12 +++++++++++ 6 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 tamer/src/nir/air/test.rs diff --git a/tamer/Cargo.toml b/tamer/Cargo.toml index 0dd9cb3e..c1d2d80d 100644 --- a/tamer/Cargo.toml +++ b/tamer/Cargo.toml @@ -52,3 +52,9 @@ unicode-width = "0.1.5" # This is enabled automatically for the `test` profile. parser-trace-stderr = [] +# Lowering NIR into AIR will begin adding objects to the graph. Since +# loweirng is not complete, this may result in errors. This flag can be +# removed when we are able to confidently state that this lowering will not +# cause issues in production TAME code. +wip-nir-to-air = [] + diff --git a/tamer/src/nir.rs b/tamer/src/nir.rs index 162bce5f..15a9cffc 100644 --- a/tamer/src/nir.rs +++ b/tamer/src/nir.rs @@ -177,15 +177,26 @@ impl Functor for Nir { /// An object upon which other [`Nir`] tokens act. #[derive(Debug, PartialEq, Eq)] pub enum NirEntity { + /// Rate (verb) block, + /// representing a calculation with a scalar result. + Rate, + /// Template parameter (metavariable). TplParam, } +impl NirEntity { + pub fn open>(self, span: S) -> Nir { + Nir::Open(self, span.into()) + } +} + impl Display for NirEntity { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { use NirEntity::*; match self { + Rate => write!(f, "rate block"), TplParam => write!(f, "template param (metavariable)"), } } diff --git a/tamer/src/nir/air.rs b/tamer/src/nir/air.rs index 8fece2f3..4de25c22 100644 --- a/tamer/src/nir/air.rs +++ b/tamer/src/nir/air.rs @@ -21,7 +21,12 @@ use std::{error::Error, fmt::Display}; -use crate::{asg::air::Air, diagnose::Diagnostic, parse::prelude::*}; +use crate::{ + asg::{air::Air, ExprOp}, + diagnose::Diagnostic, + nir::NirEntity, + parse::prelude::*, +}; use super::Nir; @@ -48,10 +53,33 @@ impl ParseState for NirToAir { fn parse_token( self, - _tok: Self::Token, + tok: Self::Token, _: NoContext, ) -> TransitionResult { - Transition(self).ok(Air::Todo) + use NirToAir::*; + + #[cfg(not(feature = "wip-nir-to-air"))] + { + let _ = tok; // prevent `unused_variables` warning + return Transition(Ready).ok(Air::Todo); + } + + #[allow(unreachable_code)] // due to wip-nir-to-air + match (self, tok) { + (Ready, Nir::Open(NirEntity::Rate, span)) => { + Transition(Ready).ok(Air::ExprOpen(ExprOp::Sum, span)) + } + + (Ready, Nir::Close(span)) => { + Transition(Ready).ok(Air::ExprClose(span)) + } + + (Ready, Nir::BindIdent(spair)) => { + Transition(Ready).ok(Air::ExprIdent(spair)) + } + + _ => Transition(Ready).ok(Air::Todo), + } } fn is_accepting(&self, _: &Self::Context) -> bool { @@ -82,3 +110,6 @@ impl Diagnostic for NirToAirError { vec![] } } + +#[cfg(all(test, feature = "wip-nir-to-air"))] +mod test; diff --git a/tamer/src/nir/air/test.rs b/tamer/src/nir/air/test.rs new file mode 100644 index 00000000..92bc793b --- /dev/null +++ b/tamer/src/nir/air/test.rs @@ -0,0 +1,45 @@ +// Test lowering NIR into AIR +// +// Copyright (C) 2014-2023 Ryan Specialty, 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 . + +use super::*; +use crate::{parse::util::SPair, span::dummy::*}; + +type Sut = NirToAir; + +use Parsed::Object as O; + +#[test] +fn rate_to_sum_expr() { + let id = SPair("foo".into(), S2); + + let toks = vec![ + Nir::Open(NirEntity::Rate, S1), + Nir::BindIdent(id), + Nir::Close(S3), + ]; + + assert_eq!( + Ok(vec![ + O(Air::ExprOpen(ExprOp::Sum, S1)), + O(Air::ExprIdent(id)), + O(Air::ExprClose(S3)), + ]), + Sut::parse(toks.into_iter()).collect(), + ); +} diff --git a/tamer/src/nir/parse.rs b/tamer/src/nir/parse.rs index 8670061c..6410c9b8 100644 --- a/tamer/src/nir/parse.rs +++ b/tamer/src/nir/parse.rs @@ -408,11 +408,11 @@ ele_parse! { /// the term originates from TAME's history as an insurance rating /// system. /// This will eventually be renamed to a more general term. - RateStmt := QN_RATE { + RateStmt := QN_RATE(_, ospan) { @ { QN_CLASS => TodoAttr, QN_NO => TodoAttr, - QN_YIELDS => TodoAttr, + QN_YIELDS => BindIdent, QN_DESC => TodoAttr, QN_SYM => TodoAttr, @@ -423,7 +423,8 @@ ele_parse! { // TODO: We'll have private-by-default later. // This is a kludge. QN_LOCAL => TodoAttr, - } => Todo, + } => NirEntity::Rate.open(ospan), + /(cspan) => Close(cspan.span()), CalcExpr, }; diff --git a/tamer/src/xir.rs b/tamer/src/xir.rs index 7b162775..d80edf7e 100644 --- a/tamer/src/xir.rs +++ b/tamer/src/xir.rs @@ -524,6 +524,18 @@ impl EleSpan for CloseSpan { } } +impl From for Span { + fn from(value: OpenSpan) -> Self { + value.span() + } +} + +impl From for Span { + fn from(value: CloseSpan) -> Self { + value.span() + } +} + /// Lightly-structured XML tokens with associated [`Span`]s. /// /// This is a streamable IR for XML.