tamer: Move SymAttrs lowering into asg_builder

asg_builder is about to be replaced, but in the process of simplifying the
destination IR (the ASG), I'm moving things into the proper place.  This
never belonged here---it belongs with the actual lowering operation.

Previously, this was not reasoned about in terms of a lowering operation,
and was written when I was first introducing myself to Rust and trying to
get a proof-of-concept linker working.

DEV-11864
main
Mike Gerwitz 2022-05-19 09:44:53 -04:00
parent 8948452b71
commit b2a79e930b
3 changed files with 236 additions and 245 deletions

View File

@ -19,10 +19,8 @@
//! Identifiers (a type of [object][super::object::IdentObject]).
use crate::obj::xmlo::{Dim as XmloDim, SymAttrs, SymDtype, SymType};
use crate::obj::xmlo::SymDtype;
use crate::sym::{st, GlobalSymbolResolve, SymbolId};
use std::convert::TryFrom;
use std::error::Error;
/// Types of identifiers.
///
@ -218,97 +216,6 @@ impl std::fmt::Display for IdentKind {
}
}
impl TryFrom<SymAttrs> for IdentKind {
type Error = IdentKindError;
/// Attempt to raise [`SymAttrs`] into an [`IdentKind`].
///
/// Certain [`IdentKind`] require that certain attributes be present,
/// otherwise the conversion will fail.
fn try_from(attrs: SymAttrs) -> Result<Self, Self::Error> {
Self::try_from(&attrs)
}
}
impl TryFrom<&SymAttrs> for IdentKind {
type Error = IdentKindError;
/// Attempt to raise [`SymAttrs`] into an [`IdentKind`].
///
/// Certain [`IdentKind`] require that certain attributes be present,
/// otherwise the conversion will fail.
fn try_from(attrs: &SymAttrs) -> Result<Self, Self::Error> {
let ty = attrs.ty.as_ref().ok_or(Self::Error::MissingType)?;
macro_rules! ident {
($to:expr) => {
Ok($to)
};
($to:expr, dim) => {
Ok($to(attrs.dim.ok_or(Self::Error::MissingDim)?.into()))
};
($to:expr, dtype) => {
Ok($to(attrs.dtype.ok_or(Self::Error::MissingDtype)?))
};
($to:expr, dim, dtype) => {
Ok($to(
attrs.dim.ok_or(Self::Error::MissingDim)?.into(),
attrs.dtype.ok_or(Self::Error::MissingDtype)?,
))
};
}
match ty {
SymType::Cgen => ident!(Self::Cgen, dim),
SymType::Class => ident!(Self::Class, dim),
SymType::Const => ident!(Self::Const, dim, dtype),
SymType::Func => ident!(Self::Func, dim, dtype),
SymType::Gen => ident!(Self::Gen, dim, dtype),
SymType::Lparam => ident!(IdentKind::Lparam, dim, dtype),
SymType::Param => ident!(IdentKind::Param, dim, dtype),
SymType::Rate => ident!(IdentKind::Rate, dtype),
SymType::Tpl => ident!(IdentKind::Tpl),
SymType::Type => ident!(IdentKind::Type, dtype),
SymType::MapHead => ident!(IdentKind::MapHead),
SymType::Map => ident!(IdentKind::Map),
SymType::MapTail => ident!(IdentKind::MapTail),
SymType::RetMapHead => ident!(IdentKind::RetMapHead),
SymType::RetMap => ident!(IdentKind::RetMap),
SymType::RetMapTail => ident!(IdentKind::RetMapTail),
SymType::Meta => ident!(IdentKind::Meta),
SymType::Worksheet => ident!(IdentKind::Worksheet),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum IdentKindError {
/// Symbol type was not provided.
MissingType,
/// Number of symbol dimensions were not provided.
MissingDim,
/// Symbol dtype was not provided.
MissingDtype,
}
impl std::fmt::Display for IdentKindError {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::MissingType => write!(fmt, "missing symbol type"),
Self::MissingDim => write!(fmt, "missing dim"),
Self::MissingDtype => write!(fmt, "missing dtype"),
}
}
}
impl Error for IdentKindError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
/// Value dimensionality.
///
/// This indicates the number of subscripts needed to access a scalar
@ -321,19 +228,6 @@ pub enum Dim {
Matrix = 2,
}
// These are clearly the same thing,
// but it's not worth sharing them until a natural shared abstraction
// arises.
impl From<XmloDim> for Dim {
fn from(dim: XmloDim) -> Self {
match dim {
XmloDim::Scalar => Dim::Scalar,
XmloDim::Vector => Dim::Vector,
XmloDim::Matrix => Dim::Matrix,
}
}
}
impl From<Dim> for u8 {
fn from(dim: Dim) -> Self {
dim as u8
@ -354,136 +248,3 @@ impl std::fmt::Display for Dim {
/// Underlying datatype of identifier.
pub type DataType = SymDtype;
#[cfg(test)]
mod test {
use super::*;
use crate::obj::xmlo::Dim as XmloDim;
use std::convert::TryInto;
macro_rules! test_kind {
($name:ident, $src:expr => $dest:expr) => {
#[test]
fn $name() {
assert_eq!(
Ok($dest),
SymAttrs {
ty: Some($src),
..Default::default()
}
.try_into()
);
}
};
($name:ident, $src:expr => $dest:expr, dim) => {
#[test]
fn $name() {
let dim = XmloDim::Vector;
assert_eq!(
Ok($dest(Dim::Vector)),
SymAttrs {
ty: Some($src),
dim: Some(dim),
..Default::default()
}
.try_into()
);
// no dim
let result = IdentKind::try_from(SymAttrs {
ty: Some($src),
..Default::default()
})
.expect_err("must fail when missing dim");
assert_eq!(IdentKindError::MissingDim, result);
}
};
($name:ident, $src:expr => $dest:expr, dtype) => {
#[test]
fn $name() {
let dtype = SymDtype::Float;
assert_eq!(
Ok($dest(dtype)),
SymAttrs {
ty: Some($src),
dtype: Some(dtype),
..Default::default()
}
.try_into()
);
// no dtype
let result = IdentKind::try_from(SymAttrs {
ty: Some($src),
..Default::default()
})
.expect_err("must fail when missing dtype");
assert_eq!(IdentKindError::MissingDtype, result);
}
};
($name:ident, $src:expr => $dest:expr, dim, dtype) => {
#[test]
fn $name() {
let dim = XmloDim::Vector;
let dtype = SymDtype::Float;
assert_eq!(
Ok($dest(Dim::Vector, dtype)),
SymAttrs {
ty: Some($src),
dim: Some(dim),
dtype: Some(dtype),
..Default::default()
}
.try_into()
);
// no dim
let dim_result = IdentKind::try_from(SymAttrs {
ty: Some($src),
dtype: Some(dtype),
..Default::default()
})
.expect_err("must fail when missing dim");
assert_eq!(IdentKindError::MissingDim, dim_result);
// no dtype
let dtype_result = IdentKind::try_from(SymAttrs {
ty: Some($src),
dim: Some(dim),
..Default::default()
})
.expect_err("must fail when missing dtype");
assert_eq!(IdentKindError::MissingDtype, dtype_result);
}
};
}
test_kind!(cgen, SymType::Cgen => IdentKind::Cgen, dim);
test_kind!(class, SymType::Class => IdentKind::Class, dim);
test_kind!(r#const, SymType::Const => IdentKind::Const, dim, dtype);
test_kind!(func, SymType::Func => IdentKind::Func, dim, dtype);
test_kind!(gen, SymType::Gen => IdentKind::Gen, dim, dtype);
test_kind!(lparam, SymType::Lparam => IdentKind::Lparam, dim, dtype);
test_kind!(param, SymType::Param => IdentKind::Param, dim, dtype);
test_kind!(rate, SymType::Rate => IdentKind::Rate, dtype);
test_kind!(tpl, SymType::Tpl => IdentKind::Tpl);
test_kind!(r#type, SymType::Type => IdentKind::Type, dtype);
test_kind!(maphead, SymType::MapHead => IdentKind::MapHead);
test_kind!(map, SymType::Map => IdentKind::Map);
test_kind!(maptail, SymType::MapTail => IdentKind::MapTail);
test_kind!(retmaphead, SymType::RetMapHead => IdentKind::RetMapHead);
test_kind!(retmap, SymType::RetMap => IdentKind::RetMap);
test_kind!(retmaptail, SymType::RetMapTail => IdentKind::RetMapTail);
test_kind!(meta, SymType::Meta => IdentKind::Meta);
test_kind!(worksheet, SymType::Worksheet => IdentKind::Worksheet);
}

View File

@ -198,7 +198,7 @@ mod object;
pub use error::AsgError;
pub use graph::{Asg, AsgResult, IndexType, ObjectRef};
pub use ident::{DataType, Dim, IdentKind, IdentKindError};
pub use ident::{DataType, Dim, IdentKind};
pub use object::{
FragmentText, IdentObject, Source, TransitionError, TransitionResult,
UnresolvedError,

View File

@ -39,15 +39,15 @@
use super::{
reader::{XmloResult, XmloToken},
XmloError,
Dim, SymAttrs, SymType, XmloError,
};
use crate::asg::{Asg, AsgError, IdentKindError, Source};
use crate::asg::{Asg, AsgError, Dim as AsgDim, IdentKind, Source};
use crate::sym::SymbolId;
use std::collections::HashSet;
use std::convert::TryInto;
use std::error::Error;
use std::fmt::Display;
use std::hash::BuildHasher;
use std::{collections::HashSet, result};
pub type Result<S> = std::result::Result<AsgBuilderState<S>, AsgBuilderError>;
@ -323,12 +323,116 @@ impl Error for AsgBuilderError {
}
}
impl TryFrom<SymAttrs> for IdentKind {
type Error = IdentKindError;
/// Attempt to raise [`SymAttrs`] into an [`IdentKind`].
///
/// Certain [`IdentKind`] require that certain attributes be present,
/// otherwise the conversion will fail.
fn try_from(attrs: SymAttrs) -> result::Result<Self, Self::Error> {
Self::try_from(&attrs)
}
}
impl TryFrom<&SymAttrs> for IdentKind {
type Error = IdentKindError;
/// Attempt to raise [`SymAttrs`] into an [`IdentKind`].
///
/// Certain [`IdentKind`] require that certain attributes be present,
/// otherwise the conversion will fail.
fn try_from(attrs: &SymAttrs) -> result::Result<Self, Self::Error> {
let ty = attrs.ty.as_ref().ok_or(Self::Error::MissingType)?;
macro_rules! ident {
($to:expr) => {
Ok($to)
};
($to:expr, dim) => {
Ok($to(attrs.dim.ok_or(Self::Error::MissingDim)?.into()))
};
($to:expr, dtype) => {
Ok($to(attrs.dtype.ok_or(Self::Error::MissingDtype)?))
};
($to:expr, dim, dtype) => {
Ok($to(
attrs.dim.ok_or(Self::Error::MissingDim)?.into(),
attrs.dtype.ok_or(Self::Error::MissingDtype)?,
))
};
}
match ty {
SymType::Cgen => ident!(Self::Cgen, dim),
SymType::Class => ident!(Self::Class, dim),
SymType::Const => ident!(Self::Const, dim, dtype),
SymType::Func => ident!(Self::Func, dim, dtype),
SymType::Gen => ident!(Self::Gen, dim, dtype),
SymType::Lparam => ident!(IdentKind::Lparam, dim, dtype),
SymType::Param => ident!(IdentKind::Param, dim, dtype),
SymType::Rate => ident!(IdentKind::Rate, dtype),
SymType::Tpl => ident!(IdentKind::Tpl),
SymType::Type => ident!(IdentKind::Type, dtype),
SymType::MapHead => ident!(IdentKind::MapHead),
SymType::Map => ident!(IdentKind::Map),
SymType::MapTail => ident!(IdentKind::MapTail),
SymType::RetMapHead => ident!(IdentKind::RetMapHead),
SymType::RetMap => ident!(IdentKind::RetMap),
SymType::RetMapTail => ident!(IdentKind::RetMapTail),
SymType::Meta => ident!(IdentKind::Meta),
SymType::Worksheet => ident!(IdentKind::Worksheet),
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum IdentKindError {
/// Symbol type was not provided.
MissingType,
/// Number of symbol dimensions were not provided.
MissingDim,
/// Symbol dtype was not provided.
MissingDtype,
}
impl std::fmt::Display for IdentKindError {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::MissingType => write!(fmt, "missing symbol type"),
Self::MissingDim => write!(fmt, "missing dim"),
Self::MissingDtype => write!(fmt, "missing dtype"),
}
}
}
impl Error for IdentKindError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
// These are clearly the same thing,
// but it's not worth sharing them until a natural shared abstraction
// arises.
impl From<Dim> for AsgDim {
fn from(dim: Dim) -> Self {
match dim {
Dim::Scalar => AsgDim::Scalar,
Dim::Vector => AsgDim::Vector,
Dim::Matrix => AsgDim::Matrix,
}
}
}
// These tests are coupled with BaseAsg, which is not ideal.
#[cfg(test)]
mod test {
use super::*;
use crate::asg::{DefaultAsg, FragmentText, IdentKind, IdentObject};
use crate::obj::xmlo::{SymAttrs, SymType};
use crate::obj::xmlo::{SymAttrs, SymDtype, SymType};
use crate::span::{DUMMY_SPAN, UNKNOWN_SPAN};
use crate::sym::GlobalSymbolIntern;
use std::collections::hash_map::RandomState;
@ -856,4 +960,130 @@ mod test {
// event.
assert!(state.is_first());
}
macro_rules! test_kind {
($name:ident, $src:expr => $dest:expr) => {
#[test]
fn $name() {
assert_eq!(
Ok($dest),
SymAttrs {
ty: Some($src),
..Default::default()
}
.try_into()
);
}
};
($name:ident, $src:expr => $dest:expr, dim) => {
#[test]
fn $name() {
let dim = Dim::Vector;
assert_eq!(
Ok($dest(AsgDim::Vector)),
SymAttrs {
ty: Some($src),
dim: Some(dim),
..Default::default()
}
.try_into()
);
// no dim
let result = IdentKind::try_from(SymAttrs {
ty: Some($src),
..Default::default()
})
.expect_err("must fail when missing dim");
assert_eq!(IdentKindError::MissingDim, result);
}
};
($name:ident, $src:expr => $dest:expr, dtype) => {
#[test]
fn $name() {
let dtype = SymDtype::Float;
assert_eq!(
Ok($dest(dtype)),
SymAttrs {
ty: Some($src),
dtype: Some(dtype),
..Default::default()
}
.try_into()
);
// no dtype
let result = IdentKind::try_from(SymAttrs {
ty: Some($src),
..Default::default()
})
.expect_err("must fail when missing dtype");
assert_eq!(IdentKindError::MissingDtype, result);
}
};
($name:ident, $src:expr => $dest:expr, dim, dtype) => {
#[test]
fn $name() {
let dim = Dim::Vector;
let dtype = SymDtype::Float;
assert_eq!(
Ok($dest(AsgDim::Vector, dtype)),
SymAttrs {
ty: Some($src),
dim: Some(dim),
dtype: Some(dtype),
..Default::default()
}
.try_into()
);
// no dim
let dim_result = IdentKind::try_from(SymAttrs {
ty: Some($src),
dtype: Some(dtype),
..Default::default()
})
.expect_err("must fail when missing dim");
assert_eq!(IdentKindError::MissingDim, dim_result);
// no dtype
let dtype_result = IdentKind::try_from(SymAttrs {
ty: Some($src),
dim: Some(dim),
..Default::default()
})
.expect_err("must fail when missing dtype");
assert_eq!(IdentKindError::MissingDtype, dtype_result);
}
};
}
test_kind!(cgen, SymType::Cgen => IdentKind::Cgen, dim);
test_kind!(class, SymType::Class => IdentKind::Class, dim);
test_kind!(r#const, SymType::Const => IdentKind::Const, dim, dtype);
test_kind!(func, SymType::Func => IdentKind::Func, dim, dtype);
test_kind!(gen, SymType::Gen => IdentKind::Gen, dim, dtype);
test_kind!(lparam, SymType::Lparam => IdentKind::Lparam, dim, dtype);
test_kind!(param, SymType::Param => IdentKind::Param, dim, dtype);
test_kind!(rate, SymType::Rate => IdentKind::Rate, dtype);
test_kind!(tpl, SymType::Tpl => IdentKind::Tpl);
test_kind!(r#type, SymType::Type => IdentKind::Type, dtype);
test_kind!(maphead, SymType::MapHead => IdentKind::MapHead);
test_kind!(map, SymType::Map => IdentKind::Map);
test_kind!(maptail, SymType::MapTail => IdentKind::MapTail);
test_kind!(retmaphead, SymType::RetMapHead => IdentKind::RetMapHead);
test_kind!(retmap, SymType::RetMap => IdentKind::RetMap);
test_kind!(retmaptail, SymType::RetMapTail => IdentKind::RetMapTail);
test_kind!(meta, SymType::Meta => IdentKind::Meta);
test_kind!(worksheet, SymType::Worksheet => IdentKind::Worksheet);
}