tamer: ir::asg::object::IdentObject: Define methods from IdentObjectData
In particular, `name` needn't return an `Option`. `fragment` also returns a copy, since it's just a `SymbolId`. (It really ought to be a newtype rather than an alias, but we'll worry about that some other time.) These changes allow us to remove some runtime panics. DEV-10859main
parent
f055cb77c2
commit
739cf7e6eb
|
@ -313,7 +313,7 @@ mod object {
|
|||
mod ident {
|
||||
use super::*;
|
||||
use tamer::ir::asg::{
|
||||
IdentKind, IdentObject, IdentObjectData, IdentObjectState, Source,
|
||||
IdentKind, IdentObject, IdentObjectState, Source,
|
||||
};
|
||||
use tamer::sym::GlobalSymbolIntern;
|
||||
|
||||
|
|
|
@ -305,7 +305,7 @@ mod test {
|
|||
None
|
||||
}
|
||||
|
||||
fn fragment(&self) -> Option<&FragmentText> {
|
||||
fn fragment(&self) -> Option<FragmentText> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,44 @@ pub enum IdentObject {
|
|||
IdentFragment(SymbolId, IdentKind, Source, FragmentText),
|
||||
}
|
||||
|
||||
impl IdentObject {
|
||||
pub fn name(&self) -> SymbolId {
|
||||
match self {
|
||||
Self::Missing(name)
|
||||
| Self::Ident(name, _, _)
|
||||
| Self::Extern(name, _, _)
|
||||
| Self::IdentFragment(name, _, _, _) => *name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> Option<&IdentKind> {
|
||||
match self {
|
||||
Self::Missing(_) => None,
|
||||
Self::Ident(_, kind, _)
|
||||
| Self::Extern(_, kind, _)
|
||||
| Self::IdentFragment(_, kind, _, _) => Some(kind),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn src(&self) -> Option<&Source> {
|
||||
match self {
|
||||
Self::Missing(_) | Self::Extern(_, _, _) => None,
|
||||
Self::Ident(_, _, src) | Self::IdentFragment(_, _, src, _) => {
|
||||
Some(src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fragment(&self) -> Option<FragmentText> {
|
||||
match self {
|
||||
Self::Missing(_) | Self::Ident(_, _, _) | Self::Extern(_, _, _) => {
|
||||
None
|
||||
}
|
||||
Self::IdentFragment(_, _, _, text) => Some(*text),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve information about an [`IdentObject`].
|
||||
///
|
||||
/// APIs should adhere to this trait rather than a concrete object type such
|
||||
|
@ -120,7 +158,7 @@ pub trait IdentObjectData {
|
|||
///
|
||||
/// If the object does not have an associated code fragment,
|
||||
/// [`None`] is returned.
|
||||
fn fragment(&self) -> Option<&FragmentText>;
|
||||
fn fragment(&self) -> Option<FragmentText>;
|
||||
|
||||
/// IdentObject as an identifier ([`IdentObject`]).
|
||||
///
|
||||
|
@ -137,39 +175,20 @@ pub trait IdentObjectData {
|
|||
|
||||
impl IdentObjectData for IdentObject {
|
||||
fn name(&self) -> Option<SymbolId> {
|
||||
match self {
|
||||
Self::Missing(name)
|
||||
| Self::Ident(name, _, _)
|
||||
| Self::Extern(name, _, _)
|
||||
| Self::IdentFragment(name, _, _, _) => Some(*name),
|
||||
}
|
||||
Some(Self::name(self))
|
||||
}
|
||||
|
||||
fn kind(&self) -> Option<&IdentKind> {
|
||||
match self {
|
||||
Self::Missing(_) => None,
|
||||
Self::Ident(_, kind, _)
|
||||
| Self::Extern(_, kind, _)
|
||||
| Self::IdentFragment(_, kind, _, _) => Some(kind),
|
||||
}
|
||||
Self::kind(self)
|
||||
}
|
||||
|
||||
fn src(&self) -> Option<&Source> {
|
||||
match self {
|
||||
Self::Missing(_) | Self::Extern(_, _, _) => None,
|
||||
Self::Ident(_, _, src) | Self::IdentFragment(_, _, src, _) => {
|
||||
Some(src)
|
||||
}
|
||||
}
|
||||
Self::src(self)
|
||||
}
|
||||
|
||||
fn fragment(&self) -> Option<&FragmentText> {
|
||||
match self {
|
||||
Self::Missing(_) | Self::Ident(_, _, _) | Self::Extern(_, _, _) => {
|
||||
None
|
||||
}
|
||||
Self::IdentFragment(_, _, _, text) => Some(text),
|
||||
}
|
||||
fn fragment(&self) -> Option<FragmentText> {
|
||||
// TODO: Get rid of the reference; the type is `Copy` now.
|
||||
Self::fragment(self)
|
||||
}
|
||||
|
||||
/// Expose underlying [`IdentObject`].
|
||||
|
@ -372,9 +391,7 @@ impl IdentObjectState<IdentObject> for IdentObject {
|
|||
}
|
||||
|
||||
_ => {
|
||||
let err = TransitionError::Redeclare {
|
||||
name: self.name().unwrap(),
|
||||
};
|
||||
let err = TransitionError::Redeclare { name: self.name() };
|
||||
|
||||
Err((self, err))
|
||||
}
|
||||
|
@ -406,11 +423,11 @@ impl IdentObjectState<IdentObject> for IdentObject {
|
|||
src: Source,
|
||||
) -> TransitionResult<IdentObject> {
|
||||
match self.kind() {
|
||||
None => Ok(IdentObject::Extern(self.name().unwrap(), kind, src)),
|
||||
None => Ok(IdentObject::Extern(self.name(), kind, src)),
|
||||
Some(cur_kind) => {
|
||||
if cur_kind != &kind {
|
||||
let err = TransitionError::ExternResolution {
|
||||
name: self.name().unwrap(),
|
||||
name: self.name(),
|
||||
expected: kind.clone(),
|
||||
given: cur_kind.clone(),
|
||||
};
|
||||
|
@ -708,22 +725,25 @@ mod test {
|
|||
fn ident_object_name() {
|
||||
let sym: SymbolId = "sym".intern();
|
||||
|
||||
assert_eq!(Some(sym), IdentObject::Missing(sym).name());
|
||||
|
||||
assert_eq!(
|
||||
Some(sym),
|
||||
IdentObjectData::name(&IdentObject::Missing(sym))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sym,
|
||||
IdentObject::Ident(sym, IdentKind::Meta, Source::default())
|
||||
.name()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Some(sym),
|
||||
sym,
|
||||
IdentObject::Extern(sym, IdentKind::Meta, Source::default())
|
||||
.name()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Some(sym),
|
||||
sym,
|
||||
IdentObject::IdentFragment(
|
||||
sym,
|
||||
IdentKind::Meta,
|
||||
|
@ -816,7 +836,7 @@ mod test {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
Some(&text),
|
||||
Some(text),
|
||||
IdentObject::IdentFragment(
|
||||
sym,
|
||||
IdentKind::Meta,
|
||||
|
|
|
@ -26,7 +26,7 @@ use super::xmle::{
|
|||
XmleSections,
|
||||
};
|
||||
use crate::global;
|
||||
use crate::ir::asg::{Asg, DefaultAsg, IdentObject, IdentObjectData};
|
||||
use crate::ir::asg::{Asg, DefaultAsg, IdentObject};
|
||||
use crate::ir::xir::writer::XmlWriter;
|
||||
use crate::obj::xmlo::{AsgBuilder, AsgBuilderState, XmloReader};
|
||||
use crate::sym::SymbolId;
|
||||
|
@ -82,20 +82,12 @@ pub fn xmle(package_path: &str, output: &str) -> Result<(), Box<dyn Error>> {
|
|||
let msg: Vec<String> = cycles
|
||||
.into_iter()
|
||||
.map(|cycle| {
|
||||
let mut path: Vec<String> = cycle
|
||||
let mut path = cycle
|
||||
.into_iter()
|
||||
.map(|obj| {
|
||||
format!(
|
||||
"{}",
|
||||
depgraph
|
||||
.get(obj)
|
||||
.unwrap()
|
||||
.name()
|
||||
.unwrap()
|
||||
.lookup_str(),
|
||||
)
|
||||
depgraph.get(obj).unwrap().name().lookup_str()
|
||||
})
|
||||
.collect();
|
||||
.collect::<Vec<&str>>();
|
||||
|
||||
path.reverse();
|
||||
path.push(path[0].clone());
|
||||
|
@ -145,7 +137,7 @@ pub fn graphml(package_path: &str, output: &str) -> Result<(), Box<dyn Error>> {
|
|||
};
|
||||
|
||||
(
|
||||
format!("{}", n.name().unwrap().lookup_str()),
|
||||
n.name().lookup_str().into(),
|
||||
n.kind().unwrap().as_sym(),
|
||||
format!("{}", generated),
|
||||
)
|
||||
|
|
|
@ -23,10 +23,7 @@
|
|||
|
||||
use super::section::{SectionsError, XmleSections};
|
||||
use crate::{
|
||||
ir::asg::{
|
||||
Asg, BaseAsg, IdentKind, IdentObject, IdentObjectData, IndexType,
|
||||
ObjectRef,
|
||||
},
|
||||
ir::asg::{Asg, BaseAsg, IdentKind, IdentObject, IndexType, ObjectRef},
|
||||
sym::{st, GlobalSymbolResolve, SymbolId},
|
||||
};
|
||||
use petgraph::visit::DfsPostOrder;
|
||||
|
|
|
@ -27,28 +27,45 @@
|
|||
//! necessary for execution.
|
||||
|
||||
use crate::ir::asg::{
|
||||
IdentKind, IdentObject, IdentObjectData, IdentObjectState, UnresolvedError,
|
||||
IdentKind, IdentObject, IdentObjectState, UnresolvedError,
|
||||
};
|
||||
use crate::sym::{GlobalSymbolResolve, SymbolId};
|
||||
use crate::sym::SymbolId;
|
||||
use fxhash::FxHashSet;
|
||||
use std::mem::take;
|
||||
use std::result::Result;
|
||||
|
||||
pub type PushResult<T = ()> = Result<T, SectionsError>;
|
||||
|
||||
/// Sections of a linked `xmle` file.
|
||||
///
|
||||
/// For more information on these sections,
|
||||
/// see the [parent module](super).
|
||||
pub trait XmleSections<'a> {
|
||||
/// Push an object into the appropriate section.
|
||||
///
|
||||
/// Objects are expected to be properly sorted relative to their order
|
||||
/// of execution so that their text fragments are placed in the
|
||||
/// correct order in the final program text.
|
||||
fn push(&mut self, ident: &'a IdentObject) -> PushResult;
|
||||
|
||||
/// Take the list of objects present in the linked file.
|
||||
///
|
||||
/// The order of these objects does not matter.
|
||||
fn take_deps(&mut self) -> Vec<&'a IdentObject>;
|
||||
|
||||
fn take_static(&mut self) -> Vec<SymbolId>;
|
||||
|
||||
/// Take the ordered text fragments for the `map` section.
|
||||
fn take_map(&mut self) -> Vec<SymbolId>;
|
||||
|
||||
/// Take the set of external identifiers mapped into this system.
|
||||
fn take_map_froms(&mut self) -> FxHashSet<SymbolId>;
|
||||
|
||||
/// Take the ordered text fragments for the `retmap` section.
|
||||
fn take_retmap(&mut self) -> Vec<SymbolId>;
|
||||
|
||||
/// Take the ordered text fragments for the `static` section.
|
||||
fn take_static(&mut self) -> Vec<SymbolId>;
|
||||
|
||||
/// Take the ordered text fragments for the `exec` section.
|
||||
fn take_exec(&mut self) -> Vec<SymbolId>;
|
||||
}
|
||||
|
||||
|
@ -58,12 +75,24 @@ pub trait XmleSections<'a> {
|
|||
/// see the [parent module](super).
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct Sections<'a> {
|
||||
/// List of objects present in the linked file.
|
||||
///
|
||||
/// The order of these objects does not matter.
|
||||
deps: Vec<&'a IdentObject>,
|
||||
|
||||
/// External identifiers mapped into this system.
|
||||
map_froms: FxHashSet<SymbolId>,
|
||||
|
||||
/// Ordered text fragments of `map` section.
|
||||
map: Vec<SymbolId>,
|
||||
|
||||
/// Order text fragments of `retmap` section.
|
||||
retmap: Vec<SymbolId>,
|
||||
|
||||
/// Ordered text fragments of `static` section.
|
||||
st: Vec<SymbolId>,
|
||||
|
||||
/// Ordered text fragments of `exec` section.
|
||||
exec: Vec<SymbolId>,
|
||||
}
|
||||
|
||||
|
@ -78,18 +107,12 @@ impl<'a> Sections<'a> {
|
|||
}
|
||||
|
||||
impl<'a> XmleSections<'a> for Sections<'a> {
|
||||
/// Push an object into the appropriate section.
|
||||
///
|
||||
/// Objects are expected to be properly sorted relative to their order
|
||||
/// of execution so that their text fragments are placed in the
|
||||
/// correct order in the final program text.
|
||||
fn push(&mut self, ident: &'a IdentObject) -> PushResult {
|
||||
self.deps.push(ident);
|
||||
|
||||
// TODO: This cannot happen, so use an API without Option.
|
||||
let name = ident.name().expect("missing identifier name");
|
||||
|
||||
let frag = ident.fragment().map(|sym| *sym);
|
||||
let name = ident.name();
|
||||
let frag = ident.fragment();
|
||||
|
||||
match ident.resolved()?.kind() {
|
||||
Some(kind) => match kind {
|
||||
|
@ -131,13 +154,7 @@ impl<'a> XmleSections<'a> for Sections<'a> {
|
|||
// compiler bug and there is no use in trying to be nice
|
||||
// about a situation where something went terribly, horribly
|
||||
// wrong.
|
||||
return Err(SectionsError::MissingObjectKind(
|
||||
ident
|
||||
.name()
|
||||
.map(|name| name.lookup_str())
|
||||
.unwrap_or("<unknown>".into())
|
||||
.into(),
|
||||
));
|
||||
return Err(SectionsError::MissingObjectKind(ident.name()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +222,7 @@ pub enum SectionsError {
|
|||
/// sections.
|
||||
/// It should never be the case that a resolved object has no kind,
|
||||
/// so this likely represents a compiler bug.
|
||||
MissingObjectKind(String),
|
||||
MissingObjectKind(SymbolId),
|
||||
}
|
||||
|
||||
impl From<UnresolvedError> for SectionsError {
|
||||
|
@ -395,7 +412,7 @@ mod test {
|
|||
($($name:ident),*) => {
|
||||
vec![
|
||||
$(&$name),*
|
||||
].into_iter().map(|x| *x.fragment().unwrap()).collect::<Vec<SymbolId>>()
|
||||
].into_iter().map(|x| x.fragment().unwrap()).collect::<Vec<SymbolId>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
use super::*;
|
||||
use crate::convert::ExpectInto;
|
||||
use crate::ir::{
|
||||
asg::{Dim, IdentKind, IdentObjectData, Source},
|
||||
asg::{Dim, IdentKind, Source},
|
||||
legacyir::SymDtype,
|
||||
xir::{
|
||||
pred::{not, open},
|
||||
|
@ -256,7 +256,7 @@ fn test_writes_deps() -> TestResult {
|
|||
|
||||
assert_eq!(
|
||||
attrs.find(QN_NAME).and_then(|a| a.value_atom()),
|
||||
Some(AttrValue::Escaped(ident.name().unwrap())),
|
||||
Some(AttrValue::Escaped(ident.name())),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in New Issue