From 7c60b53de8c9de0b788b9b57d10d1b99ded8b3ee Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Wed, 15 Jan 2020 11:24:56 -0500 Subject: [PATCH] TAMER: Virtual symbol override --- .rev-xmle | 2 +- src/current/include/preproc/symtable.xsl | 12 ++- tamer/src/ir/asg/base.rs | 99 +++++++++++++++++++++++- tamer/src/ir/asg/graph.rs | 6 ++ tamer/src/ir/asg/object.rs | 28 ++++++- tamer/src/ir/legacyir.rs | 10 +++ tamer/src/obj/xmlo/reader.rs | 18 +++++ 7 files changed, 165 insertions(+), 10 deletions(-) diff --git a/.rev-xmle b/.rev-xmle index 2253abf9..0a9afa0c 100644 --- a/.rev-xmle +++ b/.rev-xmle @@ -1,4 +1,4 @@ # This number is incremented for every linker change to force rebuilding # of xmle files. -2 +3 diff --git a/src/current/include/preproc/symtable.xsl b/src/current/include/preproc/symtable.xsl index 9d219060..700f930e 100644 --- a/src/current/include/preproc/symtable.xsl +++ b/src/current/include/preproc/symtable.xsl @@ -514,10 +514,18 @@ - + - + + + + + + diff --git a/tamer/src/ir/asg/base.rs b/tamer/src/ir/asg/base.rs index f1868c3d..ed490f73 100644 --- a/tamer/src/ir/asg/base.rs +++ b/tamer/src/ir/asg/base.rs @@ -141,13 +141,29 @@ where ) -> AsgResult> { // TODO: src check if let Some(existing) = self.lookup(name) { - match self.graph.node_weight_mut(existing.0) { - Some(node @ Some(Object::Missing(_))) => { + let node = self.graph.node_weight_mut(existing.0).unwrap(); + + match node { + Some(Object::Missing(_)) => { node.replace(Object::Ident(name, kind, src)); return Ok(existing); } - Some(_) => return Ok(existing), - _ => (), + // TODO: no override-override + Some(Object::Ident(_, _, orig_src)) + if orig_src.virtual_ && src.override_ => + { + *orig_src = src; + return Ok(existing); + } + // TODO: no override-override + Some(Object::IdentFragment(_, _, orig_src, _)) + if orig_src.virtual_ && src.override_ => + { + // clears fragment, which is no longer applicable + node.replace(Object::Ident(name, kind, src)); + return Ok(existing); + } + _ => return Ok(existing), } } @@ -414,6 +430,81 @@ mod test { Ok(()) } + // TODO: incompatible + #[test] + fn declare_override_virtual_ident() -> AsgResult<()> { + let mut sut = Sut::with_capacity(0, 0); + + let sym = Symbol::new_dummy(SymbolIndex::from_u32(1), "virtual"); + let over_src = Symbol::new_dummy(SymbolIndex::from_u32(2), "src"); + + let virt_node = sut.declare( + &sym, + IdentKind::Meta, + Source { + virtual_: true, + ..Default::default() + }, + )?; + + let over_src = Source { + override_: true, + src: Some(&over_src), + ..Default::default() + }; + + let over_node = sut.declare(&sym, IdentKind::Meta, over_src.clone())?; + + assert_eq!(virt_node, over_node); + + assert_eq!( + sut.get(over_node), + Some(&Object::Ident(&sym, IdentKind::Meta, over_src,)) + ); + + Ok(()) + } + + // TODO: incompatible + #[test] + fn declare_override_virtual_ident_fragment() -> AsgResult<()> { + let mut sut = Sut::with_capacity(0, 0); + + let sym = Symbol::new_dummy(SymbolIndex::from_u32(1), "virtual"); + let over_src = Symbol::new_dummy(SymbolIndex::from_u32(2), "src"); + + let virt_node = sut.declare( + &sym, + IdentKind::Meta, + Source { + virtual_: true, + ..Default::default() + }, + )?; + + sut.set_fragment(virt_node, FragmentText::from("remove me"))?; + + let over_src = Source { + override_: true, + src: Some(&over_src), + ..Default::default() + }; + + let over_node = sut.declare(&sym, IdentKind::Meta, over_src.clone())?; + + assert_eq!(virt_node, over_node); + + // The act of overriding the node should have cleared any existing + // fragment, making way for a new fragment to take its place as soon + // as it is discovered. (So, back to an Object::Ident.) + assert_eq!( + sut.get(over_node), + Some(&Object::Ident(&sym, IdentKind::Meta, over_src,)) + ); + + Ok(()) + } + #[test] fn add_fragment_to_ident() -> AsgResult<()> { let mut sut = Sut::with_capacity(0, 0); diff --git a/tamer/src/ir/asg/graph.rs b/tamer/src/ir/asg/graph.rs index 7be76152..e2135e4a 100644 --- a/tamer/src/ir/asg/graph.rs +++ b/tamer/src/ir/asg/graph.rs @@ -61,6 +61,12 @@ pub trait Asg<'i, Ix: IndexType> { /// [`Object::Extern`] into a [`Object::Ident`]. /// When this happens, /// the extern is said to be _resolved_. + /// + /// If a virtual identifier of type [`Object::IdentFragment`] is + /// overridden, + /// then its fragment is cleared + /// (it returns to a [`Object::Ident`]) + /// to make way for the fragment of the override. fn declare( &mut self, name: &'i Symbol<'i>, diff --git a/tamer/src/ir/asg/object.rs b/tamer/src/ir/asg/object.rs index 1921111b..282834ac 100644 --- a/tamer/src/ir/asg/object.rs +++ b/tamer/src/ir/asg/object.rs @@ -33,9 +33,9 @@ use crate::sym::Symbol; /// / \ \ /// / v v /// ((Empty)) -> (Extern) -> ((Ident)) -> ((IdentFragment)). -/// \ ^ -/// \ / -/// `--------------------` +/// \ ^ / +/// \ / \ / +/// `--------------------` `-----------' /// ``` /// /// The [`Empty`][Object::Empty] state is never directly accessable @@ -149,6 +149,22 @@ pub struct Source<'i> { /// TODO: We have `parent`, `yields`, and `from`. /// We should begin to consolodate. pub from: Option>>, + + /// Whether identifier is virtual (can be overridden). + /// + /// This feature adds complexity and will ideally be removed in the + /// future. + /// + /// See also [`override`][Source::override_]. + pub virtual_: bool, + + /// Whether identifier overrides a virtual identifier. + /// + /// This feature adds complexity and will ideally be removed in the + /// future. + /// + /// See also [`virtual_`][Source::virtual_]. + pub override_: bool, } impl<'i> From> for Source<'i> { @@ -164,6 +180,8 @@ impl<'i> From> for Source<'i> { yields: attrs.yields, desc: attrs.desc, from: attrs.from, + virtual_: attrs.virtual_, + override_: attrs.override_, } } } @@ -189,6 +207,8 @@ mod test { yields: Some(&ysym), desc: Some("sym desc".to_string()), from: Some(vec![&fsym]), + virtual_: true, + override_: true, ..Default::default() }; @@ -201,6 +221,8 @@ mod test { yields: attrs.yields, desc: Some("sym desc".to_string()), from: Some(vec![&fsym]), + virtual_: true, + override_: true, }, attrs.into(), ); diff --git a/tamer/src/ir/legacyir.rs b/tamer/src/ir/legacyir.rs index be318b2e..bdf33a8e 100644 --- a/tamer/src/ir/legacyir.rs +++ b/tamer/src/ir/legacyir.rs @@ -158,6 +158,16 @@ pub struct SymAttrs<'i> { /// - [`SymType::Func`] lists params in order (so that the compiler /// knows application order). pub from: Option>>, + + /// Whether symbol can be overridden. + /// + /// See also [`override`][SymAttrs::override_]. + pub virtual_: bool, + + /// Whether symbol is an override of a virtual symbol. + /// + /// See also [`virtual`][SymAttrs::virtual_]. + pub override_: bool, } /// Legacy symbol types. diff --git a/tamer/src/obj/xmlo/reader.rs b/tamer/src/obj/xmlo/reader.rs index 8264b147..dfc8d348 100644 --- a/tamer/src/obj/xmlo/reader.rs +++ b/tamer/src/obj/xmlo/reader.rs @@ -469,6 +469,14 @@ impl<'i, B: BufRead, I: Interner<'i>> XmloReader<'i, B, I> { }); } + b"virtual" => { + sym_attrs.virtual_ = &*attr.value == b"true"; + } + + b"isoverride" => { + sym_attrs.override_ = &*attr.value == b"true"; + } + // As this reader evolves, we may wish to provide an error // for unknown attributes so that we can be sure that we've // handled them all. @@ -1751,6 +1759,16 @@ mod test { ..Default::default() } + r#virtual: [virtual="true"] => SymAttrs { + virtual_: true, + ..Default::default() + } + + r#override: [isoverride="true"] => SymAttrs { + override_: true, + ..Default::default() + } + // Multiple attributes at once multi: [src="foo", type="class", dim="1", dtype="float", extern="true"] => SymAttrs {