tamer: asg::ident::Dim: Narrow type

This matches xmlo::Dim, and could be the same thing, if we can find a home
for it in the future; it's not worth creating such a home right now when I'm
not yet sure what else ought to live there; the duplication may be fine.

The conversion from xmlo needs to be moved, and `Dim` is going to be used
for more than just identifiers (expressions will have type inference
performed).

DEV-11864
main
Mike Gerwitz 2022-05-19 09:32:43 -04:00
parent 263cb68380
commit 8948452b71
6 changed files with 62 additions and 97 deletions

View File

@ -598,7 +598,7 @@ mod test {
let sym = "symext".intern();
let src = Source::default();
let kind = IdentKind::Class(Dim::from_u8(3));
let kind = IdentKind::Class(Dim::Matrix);
let node = sut.declare_extern(sym, kind.clone(), src.clone())?;
let resrc = Source {

View File

@ -19,7 +19,7 @@
//! Identifiers (a type of [object][super::object::IdentObject]).
use crate::obj::xmlo::{SymAttrs, SymDtype, SymType};
use crate::obj::xmlo::{Dim as XmloDim, SymAttrs, SymDtype, SymType};
use crate::sym::{st, GlobalSymbolResolve, SymbolId};
use std::convert::TryFrom;
use std::error::Error;
@ -245,14 +245,14 @@ impl TryFrom<&SymAttrs> for IdentKind {
Ok($to)
};
($to:expr, dim) => {
Ok($to(Dim(attrs.dim.ok_or(Self::Error::MissingDim)? as u8)))
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(
Dim(attrs.dim.ok_or(Self::Error::MissingDim)? as u8),
attrs.dim.ok_or(Self::Error::MissingDim)?.into(),
attrs.dtype.ok_or(Self::Error::MissingDtype)?,
))
};
@ -309,64 +309,46 @@ impl Error for IdentKindError {
}
}
/// Identifier dimensions.
/// Value dimensionality.
///
/// This determines the number of subscripts needed to access a scalar
/// This indicates the number of subscripts needed to access a scalar
/// value.
/// A value of `0` indicates a scalar;
/// a value of `1` indicates a vector;
/// a value of `2` indicates a matrix;
/// and a value of `n` indicates a multi-dimensional array of
/// depth `n`.
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub struct Dim(u8);
impl Dim {
pub fn from_u8(value: u8) -> Self {
// We don't expect to format a value this large.
// In practice, it should never exceed 2.
assert!(value < 10, "Dim value cannot exceed 9");
Self(value)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Dim {
Scalar = 0,
Vector = 1,
Matrix = 2,
}
/// Underlying datatype of identifier.
///
/// TODO: This will always be 0≤n≤9, so let's introduce a newtype for it.
impl AsRef<str> for Dim {
fn as_ref(&self) -> &str {
match self.0 {
0 => &"0",
1 => &"1",
2 => &"2",
3 => &"3",
4 => &"4",
5 => &"5",
6 => &"6",
7 => &"7",
8 => &"8",
9 => &"9",
_ => unreachable!(),
// 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.0
dim as u8
}
}
impl From<Dim> for SymbolId {
fn from(dim: Dim) -> Self {
st::decimal1(dim.0).as_sym()
st::decimal1(dim as u8).as_sym()
}
}
impl std::fmt::Display for Dim {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
(self.0).fmt(fmt)
(*self as u8).fmt(fmt)
}
}
@ -379,23 +361,6 @@ mod test {
use crate::obj::xmlo::Dim as XmloDim;
use std::convert::TryInto;
#[test]
fn dim_from_u8() {
let n = 5u8;
assert_eq!(Dim(n), Dim::from_u8(n));
}
#[test]
fn dim_to_str() {
// we'll just test high and low
let low: &str = Dim(0).as_ref();
let high: &str = Dim(9).as_ref();
assert_eq!("0", low);
assert_eq!("9", high);
}
macro_rules! test_kind {
($name:ident, $src:expr => $dest:expr) => {
#[test]
@ -417,7 +382,7 @@ mod test {
let dim = XmloDim::Vector;
assert_eq!(
Ok($dest(Dim(dim.into()))),
Ok($dest(Dim::Vector)),
SymAttrs {
ty: Some($src),
dim: Some(dim),
@ -470,7 +435,7 @@ mod test {
let dtype = SymDtype::Float;
assert_eq!(
Ok($dest(Dim(dim.into()), dtype)),
Ok($dest(Dim::Vector, dtype)),
SymAttrs {
ty: Some($src),
dim: Some(dim),

View File

@ -688,7 +688,7 @@ mod test {
#[test]
fn ident_object_kind() {
let sym: SymbolId = "sym".intern();
let kind = IdentKind::Class(Dim::from_u8(5));
let kind = IdentKind::Class(Dim::Matrix);
assert_eq!(None, IdentObject::Missing(sym).kind());
@ -872,7 +872,7 @@ mod test {
#[test]
fn ident_object() {
let sym: SymbolId = "extern".intern();
let kind = IdentKind::Class(Dim::from_u8(1));
let kind = IdentKind::Class(Dim::Vector);
let src = Source {
desc: Some("extern".into()),
..Default::default()
@ -887,7 +887,7 @@ mod test {
#[test]
fn resolved_on_extern() {
let sym: SymbolId = "extern resolved".intern();
let kind = IdentKind::Class(Dim::from_u8(1));
let kind = IdentKind::Class(Dim::Vector);
let pkg_name: SymbolId = "pkg/name".intern();
let src = Source {
pkg_name: Some(pkg_name),
@ -951,7 +951,7 @@ mod test {
#[test]
fn redeclare_compatible_resolves() {
let sym: SymbolId = "extern_re_pre".intern();
let kind = IdentKind::Class(Dim::from_u8(2));
let kind = IdentKind::Class(Dim::Matrix);
let src = Source {
desc: Some("okay".into()),
..Default::default()
@ -969,7 +969,7 @@ mod test {
#[test]
fn redeclare_compatible_resolves_post() {
let sym: SymbolId = "extern_re_post".intern();
let kind = IdentKind::Class(Dim::from_u8(1));
let kind = IdentKind::Class(Dim::Vector);
let src = Source {
desc: Some("okay".into()),
..Default::default()
@ -986,7 +986,7 @@ mod test {
#[test]
fn redeclare_another_extern() {
let sym: SymbolId = "extern_extern".intern();
let kind = IdentKind::Class(Dim::from_u8(0));
let kind = IdentKind::Class(Dim::Scalar);
let src_first = Source {
desc: Some("first src".into()),
..Default::default()
@ -1009,7 +1009,7 @@ mod test {
#[test]
fn redeclare_post_incompatible_kind() {
let sym: SymbolId = "extern_re_bad_post".intern();
let kind = IdentKind::Class(Dim::from_u8(2));
let kind = IdentKind::Class(Dim::Matrix);
let src = Source {
desc: Some("bad kind".into()),
..Default::default()
@ -1053,7 +1053,7 @@ mod test {
#[test]
fn redeclare_pre_incompatible_kind() {
let sym: SymbolId = "extern_re_bad_pre".intern();
let kind_given = IdentKind::Class(Dim::from_u8(1));
let kind_given = IdentKind::Class(Dim::Vector);
let src = Source {
desc: Some("bad kind".into()),
..Default::default()
@ -1259,7 +1259,7 @@ mod test {
// This isn't the purpose of the test, but we want to make
// sure that the non-virtual override error occurs before
// the kind error.
let bad_kind = IdentKind::Cgen(Dim::from_u8(1));
let bad_kind = IdentKind::Cgen(Dim::Vector);
let result = non_virt
.clone()
@ -1312,7 +1312,7 @@ mod test {
..Default::default()
};
let bad_kind = IdentKind::Cgen(Dim::from_u8(1));
let bad_kind = IdentKind::Cgen(Dim::Vector);
let result = virt
.clone()
.resolve(bad_kind.clone(), over_src.clone())
@ -1488,7 +1488,7 @@ mod test {
..Default::default()
};
let bad_kind = IdentKind::Cgen(Dim::from_u8(1));
let bad_kind = IdentKind::Cgen(Dim::Vector);
let result = virt_frag
.clone()
.resolve(bad_kind.clone(), over_src.clone())

View File

@ -632,7 +632,7 @@ mod test {
let sym3_node = asg
.declare(
sym3,
IdentKind::Func(Dim::default(), SymDtype::Empty),
IdentKind::Func(Dim::Scalar, SymDtype::Empty),
Source {
virtual_: true,
..Default::default()
@ -674,7 +674,7 @@ mod test {
let sym1_node = asg
.declare(
sym1,
IdentKind::Func(Dim::default(), SymDtype::Empty),
IdentKind::Func(Dim::Scalar, SymDtype::Empty),
Source {
virtual_: true,
..Default::default()
@ -696,7 +696,7 @@ mod test {
let sym3_node = asg
.declare(
sym3,
IdentKind::Func(Dim::default(), SymDtype::Empty),
IdentKind::Func(Dim::Scalar, SymDtype::Empty),
Source {
virtual_: true,
..Default::default()
@ -737,7 +737,7 @@ mod test {
let sym_node = asg
.declare(
sym,
IdentKind::Func(Dim::default(), SymDtype::Empty),
IdentKind::Func(Dim::Scalar, SymDtype::Empty),
Source {
virtual_: true,
..Default::default()
@ -747,7 +747,7 @@ mod test {
asg.declare(
dep,
IdentKind::Func(Dim::default(), SymDtype::Empty),
IdentKind::Func(Dim::Scalar, SymDtype::Empty),
Source {
virtual_: true,
..Default::default()
@ -795,7 +795,7 @@ mod test {
let sym2_node = asg
.declare(
sym2,
IdentKind::Func(Dim::default(), SymDtype::Empty),
IdentKind::Func(Dim::Scalar, SymDtype::Empty),
Source {
virtual_: true,
..Default::default()

View File

@ -288,7 +288,7 @@ mod test {
let a = IdentObject::IdentFragment(
"a".intern(),
IdentKind::Const(Dim::from_u8(0), SymDtype::Integer),
IdentKind::Const(Dim::Scalar, SymDtype::Integer),
Default::default(),
"fraga".intern(),
);
@ -327,19 +327,19 @@ mod test {
let cgen = IdentObject::Ident(
"cgen".intern(),
IdentKind::Cgen(Dim::from_u8(1)),
IdentKind::Cgen(Dim::Vector),
Default::default(),
);
let gen = IdentObject::Ident(
"gen".intern(),
IdentKind::Gen(Dim::from_u8(1), SymDtype::Integer),
IdentKind::Gen(Dim::Vector, SymDtype::Integer),
Default::default(),
);
let lparam = IdentObject::Ident(
"lparam".intern(),
IdentKind::Lparam(Dim::from_u8(1), SymDtype::Integer),
IdentKind::Lparam(Dim::Vector, SymDtype::Integer),
Default::default(),
);
@ -434,13 +434,13 @@ mod test {
let mut sut = Sections::new();
add_syms!(sut, {
cgen: IdentKind::Cgen(Dim::from_u8(1)),
class: IdentKind::Class(Dim::from_u8(2)),
const_: IdentKind::Const(Dim::from_u8(0), SymDtype::Boolean),
func: IdentKind::Func(Dim::from_u8(1), SymDtype::Integer),
gen: IdentKind::Gen(Dim::from_u8(1), SymDtype::Boolean),
lparam: IdentKind::Lparam(Dim::from_u8(2), SymDtype::Float),
param: IdentKind::Param(Dim::from_u8(0), SymDtype::Integer),
cgen: IdentKind::Cgen(Dim::Scalar),
class: IdentKind::Class(Dim::Matrix),
const_: IdentKind::Const(Dim::Scalar, SymDtype::Boolean),
func: IdentKind::Func(Dim::Vector, SymDtype::Integer),
gen: IdentKind::Gen(Dim::Vector, SymDtype::Boolean),
lparam: IdentKind::Lparam(Dim::Matrix, SymDtype::Float),
param: IdentKind::Param(Dim::Scalar, SymDtype::Integer),
rate: IdentKind::Rate(SymDtype::Integer),
tpl: IdentKind::Tpl,
ty: IdentKind::Type(SymDtype::Integer),

View File

@ -80,7 +80,7 @@ fn test_writes_deps() -> TestResult {
let objs = [
IdentObject::Ident(
"cgentest".intern(),
IdentKind::Cgen(Dim::from_u8(1)),
IdentKind::Cgen(Dim::Vector),
Source {
yields: Some("yieldsValue".intern()),
parent: Some("cparent".intern()),
@ -91,32 +91,32 @@ fn test_writes_deps() -> TestResult {
),
IdentObject::Ident(
"classtest".intern(),
IdentKind::Class(Dim::from_u8(2)),
IdentKind::Class(Dim::Matrix),
Default::default(),
),
IdentObject::Ident(
"consttest".intern(),
IdentKind::Const(Dim::from_u8(0), SymDtype::Boolean),
IdentKind::Const(Dim::Scalar, SymDtype::Boolean),
Default::default(),
),
IdentObject::Ident(
"functest".intern(),
IdentKind::Func(Dim::from_u8(1), SymDtype::Integer),
IdentKind::Func(Dim::Matrix, SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
"gentest".intern(),
IdentKind::Gen(Dim::from_u8(1), SymDtype::Boolean),
IdentKind::Gen(Dim::Matrix, SymDtype::Boolean),
Default::default(),
),
IdentObject::Ident(
"lparamtest".intern(),
IdentKind::Gen(Dim::from_u8(2), SymDtype::Float),
IdentKind::Gen(Dim::Matrix, SymDtype::Float),
Default::default(),
),
IdentObject::Ident(
"paramtest".intern(),
IdentKind::Gen(Dim::from_u8(0), SymDtype::Integer),
IdentKind::Gen(Dim::Scalar, SymDtype::Integer),
Default::default(),
),
IdentObject::Ident(
@ -484,4 +484,4 @@ macro_rules! test_exec_sec {
test_exec_sec!(test_map_exec, QN_L_MAP_EXEC, IdentKind::Map);
test_exec_sec!(test_retmap_exec, QN_L_RETMAP_EXEC, IdentKind::RetMap);
test_exec_sec!(test_static, QN_L_STATIC, IdentKind::Worksheet);
test_exec_sec!(test_exec, QN_L_EXEC, IdentKind::Class(Dim::from_u8(1)));
test_exec_sec!(test_exec, QN_L_EXEC, IdentKind::Class(Dim::Vector));