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
main
Mike Gerwitz 2023-01-23 16:30:25 -05:00
parent 39ebb74583
commit 24eecaa3fd
6 changed files with 112 additions and 6 deletions

View File

@ -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 = []

View File

@ -177,15 +177,26 @@ impl Functor<SymbolId> 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<S: Into<Span>>(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)"),
}
}

View File

@ -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<Self::Super> {
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;

View File

@ -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 <http://www.gnu.org/licenses/>.
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(),
);
}

View File

@ -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,
};

View File

@ -524,6 +524,18 @@ impl EleSpan for CloseSpan {
}
}
impl From<OpenSpan> for Span {
fn from(value: OpenSpan) -> Self {
value.span()
}
}
impl From<CloseSpan> for Span {
fn from(value: CloseSpan) -> Self {
value.span()
}
}
/// Lightly-structured XML tokens with associated [`Span`]s.
///
/// This is a streamable IR for XML.