TAMER: Virtual symbol override
parent
ab3aec980d
commit
7c60b53de8
|
@ -1,4 +1,4 @@
|
||||||
# This number is incremented for every linker change to force rebuilding
|
# This number is incremented for every linker change to force rebuilding
|
||||||
# of xmle files.
|
# of xmle files.
|
||||||
2
|
3
|
||||||
|
|
||||||
|
|
|
@ -514,10 +514,18 @@
|
||||||
<!-- overridden; we're obsolete :( -->
|
<!-- overridden; we're obsolete :( -->
|
||||||
</when>
|
</when>
|
||||||
|
|
||||||
<!-- if we've gotten this far, then the override is good; clear it -->
|
<!-- if we've gotten this far, then the override is good; clear it
|
||||||
|
so as not to trigger override errors -->
|
||||||
<when test="@override='true'">
|
<when test="@override='true'">
|
||||||
<copy>
|
<copy>
|
||||||
<sequence select="@*[ not( name()='override' ) ], *" />
|
<sequence select="@*[ not( name()='override' ) ]" />
|
||||||
|
|
||||||
|
<!-- mark this has having been overridden for the linker (see
|
||||||
|
TAMER; we'll hopefully be getting rid of overrides in the
|
||||||
|
future) -->
|
||||||
|
<attribute name="isoverride" select="'true'" />
|
||||||
|
|
||||||
|
<sequence select="*" />
|
||||||
</copy>
|
</copy>
|
||||||
</when>
|
</when>
|
||||||
|
|
||||||
|
|
|
@ -141,13 +141,29 @@ where
|
||||||
) -> AsgResult<ObjectRef<Ix>> {
|
) -> AsgResult<ObjectRef<Ix>> {
|
||||||
// TODO: src check
|
// TODO: src check
|
||||||
if let Some(existing) = self.lookup(name) {
|
if let Some(existing) = self.lookup(name) {
|
||||||
match self.graph.node_weight_mut(existing.0) {
|
let node = self.graph.node_weight_mut(existing.0).unwrap();
|
||||||
Some(node @ Some(Object::Missing(_))) => {
|
|
||||||
|
match node {
|
||||||
|
Some(Object::Missing(_)) => {
|
||||||
node.replace(Object::Ident(name, kind, src));
|
node.replace(Object::Ident(name, kind, src));
|
||||||
return Ok(existing);
|
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(())
|
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]
|
#[test]
|
||||||
fn add_fragment_to_ident() -> AsgResult<()> {
|
fn add_fragment_to_ident() -> AsgResult<()> {
|
||||||
let mut sut = Sut::with_capacity(0, 0);
|
let mut sut = Sut::with_capacity(0, 0);
|
||||||
|
|
|
@ -61,6 +61,12 @@ pub trait Asg<'i, Ix: IndexType> {
|
||||||
/// [`Object::Extern`] into a [`Object::Ident`].
|
/// [`Object::Extern`] into a [`Object::Ident`].
|
||||||
/// When this happens,
|
/// When this happens,
|
||||||
/// the extern is said to be _resolved_.
|
/// 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(
|
fn declare(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &'i Symbol<'i>,
|
name: &'i Symbol<'i>,
|
||||||
|
|
|
@ -33,9 +33,9 @@ use crate::sym::Symbol;
|
||||||
/// / \ \
|
/// / \ \
|
||||||
/// / v v
|
/// / v v
|
||||||
/// ((Empty)) -> (Extern) -> ((Ident)) -> ((IdentFragment)).
|
/// ((Empty)) -> (Extern) -> ((Ident)) -> ((IdentFragment)).
|
||||||
/// \ ^
|
/// \ ^ /
|
||||||
/// \ /
|
/// \ / \ /
|
||||||
/// `--------------------`
|
/// `--------------------` `-----------'
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The [`Empty`][Object::Empty] state is never directly accessable
|
/// The [`Empty`][Object::Empty] state is never directly accessable
|
||||||
|
@ -149,6 +149,22 @@ pub struct Source<'i> {
|
||||||
/// TODO: We have `parent`, `yields`, and `from`.
|
/// TODO: We have `parent`, `yields`, and `from`.
|
||||||
/// We should begin to consolodate.
|
/// We should begin to consolodate.
|
||||||
pub from: Option<Vec<&'i Symbol<'i>>>,
|
pub from: Option<Vec<&'i Symbol<'i>>>,
|
||||||
|
|
||||||
|
/// 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<SymAttrs<'i>> for Source<'i> {
|
impl<'i> From<SymAttrs<'i>> for Source<'i> {
|
||||||
|
@ -164,6 +180,8 @@ impl<'i> From<SymAttrs<'i>> for Source<'i> {
|
||||||
yields: attrs.yields,
|
yields: attrs.yields,
|
||||||
desc: attrs.desc,
|
desc: attrs.desc,
|
||||||
from: attrs.from,
|
from: attrs.from,
|
||||||
|
virtual_: attrs.virtual_,
|
||||||
|
override_: attrs.override_,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +207,8 @@ mod test {
|
||||||
yields: Some(&ysym),
|
yields: Some(&ysym),
|
||||||
desc: Some("sym desc".to_string()),
|
desc: Some("sym desc".to_string()),
|
||||||
from: Some(vec![&fsym]),
|
from: Some(vec![&fsym]),
|
||||||
|
virtual_: true,
|
||||||
|
override_: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -201,6 +221,8 @@ mod test {
|
||||||
yields: attrs.yields,
|
yields: attrs.yields,
|
||||||
desc: Some("sym desc".to_string()),
|
desc: Some("sym desc".to_string()),
|
||||||
from: Some(vec![&fsym]),
|
from: Some(vec![&fsym]),
|
||||||
|
virtual_: true,
|
||||||
|
override_: true,
|
||||||
},
|
},
|
||||||
attrs.into(),
|
attrs.into(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -158,6 +158,16 @@ pub struct SymAttrs<'i> {
|
||||||
/// - [`SymType::Func`] lists params in order (so that the compiler
|
/// - [`SymType::Func`] lists params in order (so that the compiler
|
||||||
/// knows application order).
|
/// knows application order).
|
||||||
pub from: Option<Vec<&'i Symbol<'i>>>,
|
pub from: Option<Vec<&'i Symbol<'i>>>,
|
||||||
|
|
||||||
|
/// 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.
|
/// Legacy symbol types.
|
||||||
|
|
|
@ -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
|
// As this reader evolves, we may wish to provide an error
|
||||||
// for unknown attributes so that we can be sure that we've
|
// for unknown attributes so that we can be sure that we've
|
||||||
// handled them all.
|
// handled them all.
|
||||||
|
@ -1751,6 +1759,16 @@ mod test {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r#virtual: [virtual="true"] => SymAttrs {
|
||||||
|
virtual_: true,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
r#override: [isoverride="true"] => SymAttrs {
|
||||||
|
override_: true,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
// Multiple attributes at once
|
// Multiple attributes at once
|
||||||
multi: [src="foo", type="class", dim="1", dtype="float", extern="true"]
|
multi: [src="foo", type="class", dim="1", dtype="float", extern="true"]
|
||||||
=> SymAttrs {
|
=> SymAttrs {
|
||||||
|
|
Loading…
Reference in New Issue