Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
path: root/tamer
diff options
context:
space:
mode:
authorMike Gerwitz <mike.gerwitz@ryansg.com>2020-03-26 00:54:20 -0400
committerMike Gerwitz <mike.gerwitz@ryansg.com>2020-03-26 09:22:21 -0400
commit4051debad2381ef66cff8c44176dd768ea911ad1 (patch)
treedb7d38383af5b54737b5a310aa49b7e85ae75a2e /tamer
parentf44549d73083836e3d3c67a96c71e4995dff7692 (diff)
downloadtame-4051debad2381ef66cff8c44176dd768ea911ad1.tar.gz
tame-4051debad2381ef66cff8c44176dd768ea911ad1.tar.bz2
tame-4051debad2381ef66cff8c44176dd768ea911ad1.zip
[DEV-7087] TAMER: Add Source to IdentObject::Extern
All of these refactoring commits to arrive at this one final change: the ability to store the source location for externs so that we can report on what package is expecting an identifier to be defined. Phew. Goodnight.
Diffstat (limited to 'tamer')
-rw-r--r--tamer/src/ir/asg/mod.rs2
-rw-r--r--tamer/src/ir/asg/object.rs57
2 files changed, 42 insertions, 17 deletions
diff --git a/tamer/src/ir/asg/mod.rs b/tamer/src/ir/asg/mod.rs
index b41b486..5176eae 100644
--- a/tamer/src/ir/asg/mod.rs
+++ b/tamer/src/ir/asg/mod.rs
@@ -80,7 +80,7 @@
//! let identb = asg.declare_extern(identb_sym, IdentKind::Meta, Source::default())?;
//!
//! assert_eq!(
-//! Some(&IdentObject::Extern(identb_sym, IdentKind::Meta)),
+//! Some(&IdentObject::Extern(identb_sym, IdentKind::Meta, Source::default())),
//! asg.get(identb),
//! );
//!
diff --git a/tamer/src/ir/asg/object.rs b/tamer/src/ir/asg/object.rs
index 1765665..0bf75e9 100644
--- a/tamer/src/ir/asg/object.rs
+++ b/tamer/src/ir/asg/object.rs
@@ -62,7 +62,13 @@ pub enum IdentObject<'i> {
/// the same name is loaded.
/// It is an error if the loaded identifier does not have a compatible
/// [`IdentKind`].
- Extern(&'i Symbol<'i>, IdentKind),
+ ///
+ /// The source location of an extern represents the location of the
+ /// extern declaration.
+ /// Once resolved, however,
+ /// the source will instead represent the location of the concrete
+ /// identifier.
+ Extern(&'i Symbol<'i>, IdentKind, Source<'i>),
/// Identifier with associated text.
///
@@ -134,7 +140,7 @@ impl<'i> IdentObjectData<'i> for IdentObject<'i> {
match self {
Self::Missing(name)
| Self::Ident(name, _, _)
- | Self::Extern(name, _)
+ | Self::Extern(name, _, _)
| Self::IdentFragment(name, _, _, _) => Some(name),
}
}
@@ -143,14 +149,14 @@ impl<'i> IdentObjectData<'i> for IdentObject<'i> {
match self {
Self::Missing(_) => None,
Self::Ident(_, kind, _)
- | Self::Extern(_, kind)
+ | Self::Extern(_, kind, _)
| Self::IdentFragment(_, kind, _, _) => Some(kind),
}
}
fn src(&self) -> Option<&Source<'i>> {
match self {
- Self::Missing(_) | Self::Extern(_, _) => None,
+ Self::Missing(_) | Self::Extern(_, _, _) => None,
Self::Ident(_, _, src) | Self::IdentFragment(_, _, src, _) => {
Some(src)
}
@@ -159,7 +165,7 @@ impl<'i> IdentObjectData<'i> for IdentObject<'i> {
fn fragment(&self) -> Option<&FragmentText> {
match self {
- Self::Missing(_) | Self::Ident(_, _, _) | Self::Extern(_, _) => {
+ Self::Missing(_) | Self::Ident(_, _, _) | Self::Extern(_, _, _) => {
None
}
Self::IdentFragment(_, _, _, text) => Some(text),
@@ -261,7 +267,7 @@ impl<'i> IdentObjectState<'i, IdentObject<'i>> for IdentObject<'i> {
Ok(self)
}
- IdentObject::Extern(name, ref orig_kind) => {
+ IdentObject::Extern(name, ref orig_kind, _) => {
if orig_kind != &kind {
let err = TransitionError::ExternResolution {
name: name.to_string(),
@@ -295,10 +301,10 @@ impl<'i> IdentObjectState<'i, IdentObject<'i>> for IdentObject<'i> {
fn extern_(
self,
kind: IdentKind,
- _src: Source<'i>,
+ src: Source<'i>,
) -> TransitionResult<IdentObject<'i>> {
match self.kind() {
- None => Ok(IdentObject::Extern(self.name().unwrap(), kind)),
+ None => Ok(IdentObject::Extern(self.name().unwrap(), kind, src)),
Some(cur_kind) => {
if cur_kind != &kind {
let err = TransitionError::ExternResolution {
@@ -562,7 +568,8 @@ mod test {
assert_eq!(
Some(&sym),
- IdentObject::Extern(&sym, IdentKind::Meta).name()
+ IdentObject::Extern(&sym, IdentKind::Meta, Source::default())
+ .name()
);
assert_eq!(
@@ -592,7 +599,8 @@ mod test {
assert_eq!(
Some(&kind),
- IdentObject::Extern(&sym, kind.clone()).kind()
+ IdentObject::Extern(&sym, kind.clone(), Source::default())
+ .kind()
);
assert_eq!(
@@ -622,7 +630,10 @@ mod test {
IdentObject::Ident(&sym, IdentKind::Meta, src.clone()).src()
);
- assert_eq!(None, IdentObject::Extern(&sym, IdentKind::Meta).src());
+ assert_eq!(
+ None,
+ IdentObject::Extern(&sym, IdentKind::Meta, src.clone()).src()
+ );
assert_eq!(
Some(&src),
@@ -651,7 +662,8 @@ mod test {
assert_eq!(
None,
- IdentObject::Extern(&sym, IdentKind::Meta).fragment()
+ IdentObject::Extern(&sym, IdentKind::Meta, Source::default())
+ .fragment()
);
assert_eq!(
@@ -719,7 +731,7 @@ mod test {
};
assert_eq!(
- Ok(IdentObject::Extern(&sym, kind.clone())),
+ Ok(IdentObject::Extern(&sym, kind.clone(), src.clone())),
IdentObject::declare(&sym).extern_(kind, src),
);
}
@@ -764,12 +776,25 @@ mod test {
fn redeclare_another_extern() {
let sym = symbol_dummy!(1, "extern_extern");
let kind = IdentKind::Class(Dim::from_u8(20));
+ let src_first = Source {
+ desc: Some("first src".into()),
+ ..Default::default()
+ };
+ let src_second = Source {
+ desc: Some("second src".into()),
+ ..Default::default()
+ };
let result = IdentObject::declare(&sym)
- .extern_(kind.clone(), Source::default())
- .and_then(|o| o.extern_(kind.clone(), Source::default()));
+ .extern_(kind.clone(), src_first.clone())
+ .and_then(|o| o.extern_(kind.clone(), src_second));
- assert_eq!(Ok(IdentObject::Extern(&sym, kind)), result);
+ // Note that, if it resolves, it should keep what is
+ // _existing_, meaning that it must keep the first src.
+ assert_eq!(
+ Ok(IdentObject::Extern(&sym, kind, src_first)),
+ result
+ );
}
// Extern first, then identifier