use crate::{eval::*, parse::*, parser::*, src_ref::*};
#[derive(Debug, Clone, PartialEq)]
pub enum Type {
Invalid,
Integer,
Scalar,
String,
Color,
Length,
Area,
Volume,
Angle,
Weight,
Vec2,
Vec3,
Vec4,
Bool,
List(ListType),
Map(MapType),
UnnamedTuple(UnnamedTupleType),
NamedTuple(NamedTupleType),
Custom(QualifiedName),
Node,
}
impl Type {
pub fn default_unit(&self) -> Unit {
match self {
Self::Length => Unit::Mm,
Self::Angle => Unit::Rad,
Self::List(t) => t.ty().default_unit(),
_ => Unit::None,
}
}
pub fn is_named_tuple(&self) -> bool {
matches!(self, Self::NamedTuple(_))
}
pub fn is_list_of(&self, ty: &Type) -> bool {
match self {
Self::List(list_type) => &list_type.ty() == ty,
_ => false,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeAnnotation(pub Refer<Type>);
impl SrcReferrer for TypeAnnotation {
fn src_ref(&self) -> SrcRef {
self.0.src_ref()
}
}
impl std::fmt::Display for TypeAnnotation {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Ty for TypeAnnotation {
fn ty(&self) -> Type {
self.0.value.clone()
}
}
impl From<Type> for TypeAnnotation {
fn from(value: Type) -> Self {
TypeAnnotation(Refer::none(value))
}
}
impl Parse for TypeAnnotation {
fn parse(pair: Pair) -> ParseResult<Self> {
Parser::ensure_rule(&pair, Rule::r#type);
let inner = pair.inner().next().expect("Expected type");
let s = match inner.as_rule() {
Rule::list_type => Self(Refer::new(Type::List(ListType::parse(inner)?), pair.into())),
Rule::map_type => Self(Refer::new(Type::Map(MapType::parse(inner)?), pair.into())),
Rule::unnamed_tuple_type => Self(Refer::new(
Type::UnnamedTuple(UnnamedTupleType::parse(inner)?),
pair.into(),
)),
Rule::named_tuple_type => Self(Refer::new(
Type::NamedTuple(NamedTupleType::parse(inner)?),
pair.into(),
)),
Rule::qualified_name => match inner.as_str() {
"int" => Self(Refer::new(Type::Integer, pair.into())),
"scalar" => Self(Refer::new(Type::Scalar, pair.into())),
"string" => Self(Refer::new(Type::String, pair.into())),
"color" => Self(Refer::new(Type::Color, pair.into())),
"length" => Self(Refer::new(Type::Length, pair.into())),
"angle" => Self(Refer::new(Type::Angle, pair.into())),
"vec2" => Self(Refer::new(Type::Vec2, pair.into())),
"vec3" => Self(Refer::new(Type::Vec3, pair.into())),
"bool" => Self(Refer::new(Type::Bool, pair.into())),
_ => Self(Refer::new(
Type::Custom(QualifiedName::parse(inner)?),
pair.into(),
)),
},
_ => unreachable!("Expected type, found {:?}", inner.as_rule()),
};
Ok(s)
}
}
impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Invalid => write!(f, "invalid"),
Self::Integer => write!(f, "int"),
Self::Scalar => write!(f, "scalar"),
Self::String => write!(f, "string"),
Self::Color => write!(f, "color"),
Self::Length => write!(f, "length"),
Self::Area => write!(f, "area"),
Self::Volume => write!(f, "volume"),
Self::Angle => write!(f, "angle"),
Self::Weight => write!(f, "weight"),
Self::Vec2 => write!(f, "vec2"),
Self::Vec3 => write!(f, "vec3"),
Self::Vec4 => write!(f, "vec4"),
Self::Bool => write!(f, "bool"),
Self::List(t) => write!(f, "{}", t),
Self::Map(t) => write!(f, "{}", t),
Self::UnnamedTuple(t) => write!(f, "{}", t),
Self::NamedTuple(t) => write!(f, "{}", t),
Self::Custom(qn) => write!(f, "{}", qn),
Self::Node => write!(f, "{{}}"),
}
}
}
#[test]
fn builtin_type() {
let ty = Parser::parse_rule::<TypeAnnotation>(Rule::r#type, "int", 0).expect("test error");
assert_eq!(ty.0.to_string(), "int");
assert_eq!(ty.0.value, Type::Integer);
}