From 0f93f3a498b5d3d444b53cc4bd596f53ac83be5f Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Tue, 18 Jul 2023 12:31:28 -0400 Subject: [PATCH] tamer: NIR->xmli interpolation and template param The fixpoint tests for `meta-interp` are finally working. I could have broken this up more, but I'm exhausted with this process, so, you get what you get. NIR will now recognize basic `` and `` nodes (note the caveat for `` in the comment, for now), and I finally include abstract binding in the lowering pipeline. `xmli` output is also now able to cope with metavariables with a single lexical association, and continues to become more of a mess. DEV-13163 --- tamer/src/asg/air/expr.rs | 2 +- tamer/src/asg/air/meta.rs | 2 +- tamer/src/asg/air/tpl.rs | 2 +- tamer/src/asg/graph/object.rs | 16 +++++- tamer/src/asg/graph/xmli.rs | 65 +++++++++++++++++------- tamer/src/nir/parse.rs | 12 +++-- tamer/src/pipeline.rs | 6 ++- tamer/tests/xmli/meta-interp/no-fixpoint | 0 tamer/tests/xmli/template/expected.xml | 18 +++++++ tamer/tests/xmli/template/src.xml | 19 +++++++ 10 files changed, 116 insertions(+), 26 deletions(-) delete mode 100644 tamer/tests/xmli/meta-interp/no-fixpoint diff --git a/tamer/src/asg/air/expr.rs b/tamer/src/asg/air/expr.rs index a0ba8801..a6e1497c 100644 --- a/tamer/src/asg/air/expr.rs +++ b/tamer/src/asg/air/expr.rs @@ -167,7 +167,7 @@ impl ParseState for AirExprAggregate { } (BuildingExpr(es, oi), AirDoc(DocIndepClause(clause))) => { - oi.desc_short(ctx.asg_mut(), clause); + oi.add_desc_short(ctx.asg_mut(), clause); Transition(BuildingExpr(es, oi)).incomplete() } diff --git a/tamer/src/asg/air/meta.rs b/tamer/src/asg/air/meta.rs index e9a7c990..b26a3350 100644 --- a/tamer/src/asg/air/meta.rs +++ b/tamer/src/asg/air/meta.rs @@ -102,7 +102,7 @@ impl ParseState for AirMetaAggregate { } (TplMeta(oi_meta), AirDoc(DocIndepClause(clause))) => { - oi_meta.desc_short(ctx.asg_mut(), clause); + oi_meta.add_desc_short(ctx.asg_mut(), clause); Transition(TplMeta(oi_meta)).incomplete() } diff --git a/tamer/src/asg/air/tpl.rs b/tamer/src/asg/air/tpl.rs index 5792f515..5d488165 100644 --- a/tamer/src/asg/air/tpl.rs +++ b/tamer/src/asg/air/tpl.rs @@ -205,7 +205,7 @@ impl ParseState for AirTplAggregate { } (Toplevel(tpl), AirDoc(DocIndepClause(clause))) => { - tpl.oi().desc_short(ctx.asg_mut(), clause); + tpl.oi().add_desc_short(ctx.asg_mut(), clause); Transition(Toplevel(tpl)).incomplete() } diff --git a/tamer/src/asg/graph/object.rs b/tamer/src/asg/graph/object.rs index e64677ad..250eb3e0 100644 --- a/tamer/src/asg/graph/object.rs +++ b/tamer/src/asg/graph/object.rs @@ -837,13 +837,27 @@ impl ObjectIndex { /// simple sentence or as part of a compound sentence. /// There should only be one such clause for any given object, /// but that is not enforced here. - pub fn desc_short(&self, asg: &mut Asg, clause: SPair) -> Self + pub fn add_desc_short(&self, asg: &mut Asg, clause: SPair) -> Self where O: ObjectRelTo, { let oi_doc = asg.create(Doc::new_indep_clause(clause)); self.add_edge_to(asg, oi_doc, None) } + + /// Retrieve a description of this expression using a short independent + /// clause, + /// if one has been set. + /// + /// See [`Self::add_desc_short`] to add such a description. + pub fn desc_short(&self, asg: &Asg) -> Option + where + O: ObjectRelTo, + { + self.edges_filtered::(asg) + .map(ObjectIndex::cresolve(asg)) + .find_map(Doc::indep_clause) + } } impl ObjectIndex { diff --git a/tamer/src/asg/graph/xmli.rs b/tamer/src/asg/graph/xmli.rs index 1a95013e..d452f1ab 100644 --- a/tamer/src/asg/graph/xmli.rs +++ b/tamer/src/asg/graph/xmli.rs @@ -476,6 +476,28 @@ impl<'a> TreeContext<'a> { if let Some(pname) = oi_meta.ident(self.asg).map(|oi| oi.name_or_meta(self.asg)) { + // This may have a body that is a single lexeme, + // representing a default value for the parameter. + if let Some(lexeme) = meta.lexeme() { + let open = self.emit_text_node( + lexeme, + lexeme.span(), + depth.child_depth(), + ); + self.push(open); + } + + // Because of the above, + // we must check here if we have a description rather than + // waiting to encounter it during the traversal; + // otherwise we'd be outputting child nodes before a + // description attribute, + // which would result in invalid XML that is rejected by + // the XIR writer. + if let Some(desc_short) = oi_meta.desc_short(self.asg) { + self.push(attr_desc(desc_short)); + } + self.push(attr_name(pname)); Some(Xirf::open( @@ -484,22 +506,7 @@ impl<'a> TreeContext<'a> { depth, )) } else if let Some(lexeme) = meta.lexeme() { - self.push(Xirf::close( - Some(QN_TEXT), - CloseSpan::without_name_span(meta.span()), - depth, - )); - - self.push(Xirf::text( - Text(lexeme.symbol(), lexeme.span()), - depth.child_depth(), - )); - - Some(Xirf::open( - QN_TEXT, - OpenSpan::without_name_span(meta.span()), - depth, - )) + Some(self.emit_text_node(lexeme, meta.span(), depth)) } else { // TODO: Rewrite the above to be an exhaustive match, perhaps, // so we know what we'll error on. @@ -510,6 +517,27 @@ impl<'a> TreeContext<'a> { } } + /// Emit a `` node containing a lexeme. + fn emit_text_node( + &mut self, + lexeme: SPair, + node_span: Span, + depth: Depth, + ) -> Xirf { + self.push(Xirf::close( + Some(QN_TEXT), + CloseSpan::without_name_span(node_span), + depth, + )); + + self.push(Xirf::text( + Text(lexeme.symbol(), lexeme.span()), + depth.child_depth(), + )); + + Xirf::open(QN_TEXT, OpenSpan::without_name_span(node_span), depth) + } + /// Emit a `` node assumed to be within a template param /// body. fn emit_tpl_param_value( @@ -586,10 +614,11 @@ impl<'a> TreeContext<'a> { } // template/param/@desc - (Object::Meta(_), Doc::IndepClause(desc)) + (Object::Meta(_), Doc::IndepClause(_desc)) if self.tpl_apply.is_none() => { - Some(attr_desc(*desc)) + // This is already covered in `emit_tpl_param` + None } (_, Doc::Text(_text)) => { diff --git a/tamer/src/nir/parse.rs b/tamer/src/nir/parse.rs index d4f13424..c5a85c4f 100644 --- a/tamer/src/nir/parse.rs +++ b/tamer/src/nir/parse.rs @@ -1458,10 +1458,16 @@ ele_parse! { /// providing constant values. /// The result will be as if the user typed the text themselves in the /// associated template application argument. + /// + /// TODO: This just produces a no-op right now and lets the text hander + /// produce text for the inner character data. + /// This is consequently ambiguous with omitting this node entirely; + /// this might be okay, + /// but this needs explicit design. TplText := QN_TEXT(_, ospan) { @ { QN_UNIQUE => TodoAttr, - } => Todo(ospan.into()), + } => Noop(ospan.into()), }; /// Default the param to the value of another template param, @@ -1475,7 +1481,7 @@ ele_parse! { /// cumbersome and slow TplParamValue := QN_PARAM_VALUE(_, ospan) { @ { - QN_NAME => TodoAttr, + QN_NAME => Ref, QN_DASH => TodoAttr, QN_UPPER => TodoAttr, QN_LOWER => TodoAttr, @@ -1484,7 +1490,7 @@ ele_parse! { QN_RMUNDERSCORE => TodoAttr, QN_IDENTIFIER => TodoAttr, QN_SNAKE => TodoAttr, - } => Todo(ospan.into()), + } => Noop(ospan.into()), }; /// Inherit a default value from a metavalue. diff --git a/tamer/src/pipeline.rs b/tamer/src/pipeline.rs index cb2a5b74..f6c4f102 100644 --- a/tamer/src/pipeline.rs +++ b/tamer/src/pipeline.rs @@ -110,7 +110,10 @@ use crate::{ asg::{air::AirAggregate, AsgTreeToXirf}, diagnose::Diagnostic, - nir::{InterpolateNir, NirToAir, TplShortDesugar, XirfToNir}, + nir::{ + AbstractBindTranslate, InterpolateNir, NirToAir, TplShortDesugar, + XirfToNir, + }, obj::xmlo::{XmloReader, XmloToAir, XmloToken}, parse::{ terminal, FinalizeError, Lower, LowerSource, ParseError, ParseState, @@ -150,6 +153,7 @@ lower_pipeline! { |> XirfToNir |> TplShortDesugar |> InterpolateNir + |> AbstractBindTranslate |> NirToAir[nir_air_ty] |> AirAggregate[air_ctx]; diff --git a/tamer/tests/xmli/meta-interp/no-fixpoint b/tamer/tests/xmli/meta-interp/no-fixpoint deleted file mode 100644 index e69de29b..00000000 diff --git a/tamer/tests/xmli/template/expected.xml b/tamer/tests/xmli/template/expected.xml index 956e518b..3e725c2c 100644 --- a/tamer/tests/xmli/template/expected.xml +++ b/tamer/tests/xmli/template/expected.xml @@ -195,5 +195,23 @@ + + + diff --git a/tamer/tests/xmli/template/src.xml b/tamer/tests/xmli/template/src.xml index 5ff5c35f..088858c4 100644 --- a/tamer/tests/xmli/template/src.xml +++ b/tamer/tests/xmli/template/src.xml @@ -186,6 +186,7 @@ we cannot support the generation of each of those things within templates. + @@ -194,5 +195,23 @@ + + +