use enum_as_inner::EnumAsInner;
use crate::Span;
use crate::pr::path::Path;
use crate::resolver::NS_STD;
use super::Ref;
#[derive(Debug, Clone)]
pub struct Ty {
pub kind: TyKind,
pub span: Option<Span>,
pub name: Option<String>,
pub scope_id: Option<usize>,
pub target: Option<Ref>,
pub variants_force_ptr: Vec<u16>,
}
#[derive(Debug, Clone)]
pub struct TyLayout {
pub head_size: u32,
pub body_ptrs: Vec<u32>,
}
#[derive(Debug, Clone, PartialEq, Hash, EnumAsInner, strum::AsRefStr)]
pub enum TyKind {
Ident(Path),
Primitive(TyPrimitive),
Tuple(Vec<TyTupleField>),
Array(Box<Ty>),
Option(Box<Ty>),
Enum(Vec<TyEnumVariant>),
Func(TyFunc),
TupleComprehension(TyTupleComprehension),
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct TyTupleField {
pub name: Option<String>,
pub unpack: bool,
pub ty: Ty,
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct TyEnumVariant {
pub name: String,
pub ty: Ty,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, strum::Display)]
#[allow(non_camel_case_types)]
pub enum TyPrimitive {
prim8,
prim16,
prim32,
prim64,
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct TyFunc {
pub params: Vec<TyFuncParam>,
pub body: Option<Box<Ty>>,
pub ty_params: Vec<TyParam>,
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct TyFuncParam {
pub constant: bool,
pub label: Option<String>,
pub ty: Option<Ty>,
}
impl TyFuncParam {
pub fn simple(ty: Option<Ty>) -> Self {
TyFuncParam {
constant: false,
label: None,
ty,
}
}
}
#[derive(Debug, Clone)]
pub struct TyParam {
pub name: String,
pub domain: TyDomain,
pub span: Option<Span>,
}
#[derive(Debug, Clone)]
pub enum TyDomain {
Open,
OneOf(Vec<Ty>),
TupleHasFields(Vec<TyDomainTupleField>),
TupleLen { n: usize },
EnumVariants(Vec<TyDomainEnumVariant>),
}
#[derive(Clone)]
pub struct TyDomainTupleField {
pub location: super::Lookup,
pub ty: Ty,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct TyDomainEnumVariant {
pub name: String,
pub ty: Ty,
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct TyTupleComprehension {
pub tuple: Box<Ty>,
pub variable_name: String,
pub variable_ty: String,
pub body_name: Option<String>,
pub body_ty: Box<Ty>,
}
impl Ty {
pub fn new(kind: impl Into<TyKind>) -> Ty {
Ty {
kind: kind.into(),
span: None,
name: None,
target: None,
scope_id: None,
variants_force_ptr: Vec::new(),
}
}
pub fn new_with_span(kind: impl Into<TyKind>, span: Span) -> Ty {
Ty {
kind: kind.into(),
span: Some(span),
name: None,
target: None,
scope_id: None,
variants_force_ptr: Vec::new(),
}
}
pub fn new_std(name: &str) -> Self {
Ty::new(TyKind::Ident(Path::new([NS_STD, name])))
}
pub fn with_span(mut self, span: Span) -> Self {
self.span = Some(span);
self
}
}
impl From<TyPrimitive> for TyKind {
fn from(value: TyPrimitive) -> Self {
TyKind::Primitive(value)
}
}
impl From<TyFunc> for TyKind {
fn from(value: TyFunc) -> Self {
TyKind::Func(value)
}
}
impl From<Path> for TyKind {
fn from(value: Path) -> Self {
TyKind::Ident(value)
}
}
impl PartialEq for Ty {
fn eq(&self, other: &Self) -> bool {
self.kind == other.kind
}
}
impl Eq for Ty {}
impl std::hash::Hash for Ty {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.kind.hash(state);
}
}
impl PartialEq for TyParam {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for TyParam {}
impl std::hash::Hash for TyParam {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl TyTupleField {
pub(crate) fn matches_name(&self, name: &str) -> bool {
self.name.as_ref().is_some_and(|n| n == name)
}
}
impl std::fmt::Debug for TyDomainTupleField {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TyDomainTupleField")
.field("location", &self.location)
.field("ty", &self.ty)
.finish()
}
}