use crate::{
load::ModuleLoader,
model::{
annotations::{Annotation, AnnotationBuilder, AnnotationProperty, HasAnnotations},
check::{MaybeIncomplete, Validate},
constraints::{FunctionBody, FunctionCardinality, FunctionSignature},
identifiers::{Identifier, IdentifierReference},
modules::Module,
values::Value,
HasName, HasOptionalBody, HasSourceSpan, References, Span,
},
store::ModuleStore,
};
use sdml_errors::diagnostics::functions::IdentifierCaseConvention;
use std::collections::{BTreeMap, BTreeSet};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct TypeClassDef {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
span: Option<Span>,
name: Identifier,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
variables: Vec<TypeVariable>, #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
body: Option<TypeClassBody>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct TypeVariable {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
span: Option<Span>,
name: Identifier,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
cardinality: Option<FunctionCardinality>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
restrictions: Vec<TypeClassReference>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct TypeClassReference {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
span: Option<Span>,
name: IdentifierReference,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
arguments: Vec<TypeClassArgument>, }
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub enum TypeClassArgument {
Wildcard,
Reference(Box<TypeClassReference>),
}
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct TypeClassBody {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
span: Option<Span>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
annotations: Vec<Annotation>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "BTreeMap::is_empty"))]
methods: BTreeMap<Identifier, MethodDef>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct MethodDef {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
span: Option<Span>,
signature: FunctionSignature,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
body: Option<FunctionBody>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
annotations: Vec<Annotation>,
}
impl HasName for TypeClassDef {
fn name(&self) -> &Identifier {
&self.name
}
fn set_name(&mut self, name: Identifier) {
self.name = name;
}
}
impl HasOptionalBody for TypeClassDef {
type Body = TypeClassBody;
fn body(&self) -> Option<&Self::Body> {
self.body.as_ref()
}
fn body_mut(&mut self) -> Option<&mut Self::Body> {
self.body.as_mut()
}
fn set_body(&mut self, body: Self::Body) {
self.body = Some(body);
}
fn unset_body(&mut self) {
self.body = None;
}
}
impl HasSourceSpan for TypeClassDef {
fn with_source_span(self, span: Span) -> Self {
let mut self_mut = self;
self_mut.span = Some(span);
self_mut
}
fn source_span(&self) -> Option<&Span> {
self.span.as_ref()
}
fn set_source_span(&mut self, span: Span) {
self.span = Some(span);
}
fn unset_source_span(&mut self) {
self.span = None;
}
}
impl AnnotationBuilder for TypeClassDef {
fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
where
Self: Sized,
I: Into<IdentifierReference>,
V: Into<Value>,
{
let mut self_mut = self;
if let Some(ref mut inner) = self_mut.body {
inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
}
self_mut
}
}
impl MaybeIncomplete for TypeClassDef {
fn is_incomplete(&self, _: &Module, _: &impl ModuleStore) -> bool {
self.body.is_none()
}
}
impl References for TypeClassDef {
fn referenced_types<'a>(&'a self, _names: &mut BTreeSet<&'a IdentifierReference>) {}
fn referenced_annotations<'a>(&'a self, _names: &mut BTreeSet<&'a IdentifierReference>) {}
}
impl Validate for TypeClassDef {
fn validate(
&self,
top: &crate::model::modules::Module,
_cache: &impl ModuleStore,
loader: &impl ModuleLoader,
_check_constraints: bool,
) {
self.name()
.validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
todo!()
}
}
impl TypeClassDef {
pub fn new<I>(name: Identifier, variables: I) -> Self
where
I: IntoIterator<Item = TypeVariable>,
{
Self {
span: None,
name,
variables: Vec::from_iter(variables),
body: None,
}
}
pub fn has_variables(&self) -> bool {
!self.variables.is_empty()
}
pub fn variable_count(&self) -> usize {
self.variables.len()
}
pub fn variables(&self) -> impl Iterator<Item = &TypeVariable> {
self.variables.iter()
}
pub fn variables_mut(&mut self) -> impl Iterator<Item = &mut TypeVariable> {
self.variables.iter_mut()
}
pub fn add_to_variables<I>(&mut self, value: I)
where
I: Into<TypeVariable>,
{
self.variables.push(value.into())
}
pub fn extend_variables<I>(&mut self, extension: I)
where
I: IntoIterator<Item = TypeVariable>,
{
self.variables.extend(extension)
}
}
impl HasName for TypeVariable {
fn name(&self) -> &Identifier {
&self.name
}
fn set_name(&mut self, name: Identifier) {
self.name = name;
}
}
impl HasSourceSpan for TypeVariable {
fn with_source_span(self, span: Span) -> Self {
let mut self_mut = self;
self_mut.span = Some(span);
self_mut
}
fn source_span(&self) -> Option<&Span> {
self.span.as_ref()
}
fn set_source_span(&mut self, span: Span) {
self.span = Some(span);
}
fn unset_source_span(&mut self) {
self.span = None;
}
}
impl TypeVariable {
pub const fn new(name: Identifier) -> Self {
Self {
span: None,
name,
cardinality: None,
restrictions: Vec::new(),
}
}
pub fn with_cardinality(self, cardinality: FunctionCardinality) -> Self {
Self {
cardinality: Some(cardinality),
..self
}
}
pub fn with_restrictions<I>(self, restrictions: I) -> Self
where
I: IntoIterator<Item = TypeClassReference>,
{
Self {
restrictions: Vec::from_iter(restrictions),
..self
}
}
pub const fn has_cardinality(&self) -> bool {
self.cardinality.is_some()
}
pub const fn cardinality(&self) -> Option<&FunctionCardinality> {
self.cardinality.as_ref()
}
pub fn set_cardinality(&mut self, cardinality: FunctionCardinality) {
self.cardinality = Some(cardinality);
}
pub fn unset_cardinality(&mut self) {
self.cardinality = None;
}
pub fn has_restrictions(&self) -> bool {
!self.restrictions.is_empty()
}
pub fn restrictions_len(&self) -> usize {
self.restrictions.len()
}
pub fn restrictions(&self) -> impl Iterator<Item = &TypeClassReference> {
self.restrictions.iter()
}
pub fn restrictions_mut(&mut self) -> impl Iterator<Item = &mut TypeClassReference> {
self.restrictions.iter_mut()
}
pub fn add_to_restrictions<I>(&mut self, value: I)
where
I: Into<TypeClassReference>,
{
self.restrictions.push(value.into())
}
pub fn extend_restrictions<I>(&mut self, extension: I)
where
I: IntoIterator<Item = TypeClassReference>,
{
self.restrictions.extend(extension)
}
}
impl HasSourceSpan for TypeClassReference {
fn with_source_span(self, span: Span) -> Self {
let mut self_mut = self;
self_mut.span = Some(span);
self_mut
}
fn source_span(&self) -> Option<&Span> {
self.span.as_ref()
}
fn set_source_span(&mut self, span: Span) {
self.span = Some(span);
}
fn unset_source_span(&mut self) {
self.span = None;
}
}
impl TypeClassReference {
pub const fn new(name: IdentifierReference) -> Self {
Self {
span: None,
name,
arguments: Vec::new(),
}
}
pub fn with_arguments<I>(self, arguments: I) -> Self
where
I: IntoIterator<Item = TypeClassArgument>,
{
Self {
arguments: Vec::from_iter(arguments),
..self
}
}
pub const fn name(&self) -> &IdentifierReference {
&self.name
}
pub fn set_name(&mut self, name: IdentifierReference) {
self.name = name;
}
pub fn has_arguments(&self) -> bool {
!self.arguments.is_empty()
}
pub fn arguments_len(&self) -> usize {
self.arguments.len()
}
pub fn arguments(&self) -> impl Iterator<Item = &TypeClassArgument> {
self.arguments.iter()
}
pub fn arguments_mut(&mut self) -> impl Iterator<Item = &mut TypeClassArgument> {
self.arguments.iter_mut()
}
pub fn add_to_arguments<I>(&mut self, value: I)
where
I: Into<TypeClassArgument>,
{
self.arguments.push(value.into())
}
pub fn extend_arguments<I>(&mut self, extension: I)
where
I: IntoIterator<Item = TypeClassArgument>,
{
self.arguments.extend(extension)
}
}
impl TypeClassArgument {
pub const fn is_wildcard(&self) -> bool {
matches!(self, Self::Wildcard)
}
pub const fn is_reference(&self) -> bool {
matches!(self, Self::Reference(_))
}
pub const fn as_reference(&self) -> Option<&TypeClassReference> {
match self {
Self::Reference(v) => Some(v),
_ => None,
}
}
}
impl HasSourceSpan for TypeClassBody {
fn with_source_span(self, span: Span) -> Self {
let mut self_mut = self;
self_mut.span = Some(span);
self_mut
}
fn source_span(&self) -> Option<&Span> {
self.span.as_ref()
}
fn set_source_span(&mut self, span: Span) {
self.span = Some(span);
}
fn unset_source_span(&mut self) {
self.span = None;
}
}
impl HasAnnotations for TypeClassBody {
fn has_annotations(&self) -> bool {
!self.annotations.is_empty()
}
fn annotation_count(&self) -> usize {
self.annotations.len()
}
fn annotations(&self) -> impl Iterator<Item = &Annotation> {
self.annotations.iter()
}
fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
self.annotations.iter_mut()
}
fn add_to_annotations<I>(&mut self, value: I)
where
I: Into<Annotation>,
{
self.annotations.push(value.into())
}
fn extend_annotations<I>(&mut self, extension: I)
where
I: IntoIterator<Item = Annotation>,
{
self.annotations.extend(extension)
}
}
impl TypeClassBody {
pub fn with_methods<I>(self, methods: I) -> Self
where
I: IntoIterator<Item = MethodDef>,
{
Self {
methods: methods
.into_iter()
.map(|elem| (elem.name().clone(), elem))
.collect(),
..self
}
}
pub fn has_methods(&self) -> bool {
!self.methods.is_empty()
}
pub fn method_count(&self) -> usize {
self.methods.len()
}
pub fn contains_method(&self, name: &Identifier) -> bool {
self.methods.contains_key(name)
}
pub fn method(&self, name: &Identifier) -> Option<&MethodDef> {
self.methods.get(name)
}
pub fn method_mut(&mut self, name: &Identifier) -> Option<&mut MethodDef> {
self.methods.get_mut(name)
}
pub fn methods(&self) -> impl Iterator<Item = &MethodDef> {
self.methods.values()
}
pub fn methods_mut(&mut self) -> impl Iterator<Item = &mut MethodDef> {
self.methods.values_mut()
}
pub fn method_names(&self) -> impl Iterator<Item = &Identifier> {
self.methods.keys()
}
pub fn add_to_methods(&mut self, value: MethodDef) -> Option<MethodDef> {
self.methods.insert(value.name().clone(), value)
}
pub fn extend_methods<I>(&mut self, extension: I)
where
I: IntoIterator<Item = MethodDef>,
{
self.methods.extend(
extension
.into_iter()
.map(|elem| (elem.name().clone(), elem)),
)
}
}
impl HasAnnotations for MethodDef {
fn has_annotations(&self) -> bool {
!self.annotations.is_empty()
}
fn annotation_count(&self) -> usize {
self.annotations.len()
}
fn annotations(&self) -> impl Iterator<Item = &Annotation> {
self.annotations.iter()
}
fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
self.annotations.iter_mut()
}
fn add_to_annotations<I>(&mut self, value: I)
where
I: Into<Annotation>,
{
self.annotations.push(value.into())
}
fn extend_annotations<I>(&mut self, extension: I)
where
I: IntoIterator<Item = Annotation>,
{
self.annotations.extend(extension)
}
}
impl HasOptionalBody for MethodDef {
type Body = FunctionBody;
fn body(&self) -> Option<&Self::Body> {
self.body.as_ref()
}
fn body_mut(&mut self) -> Option<&mut Self::Body> {
self.body.as_mut()
}
fn set_body(&mut self, body: Self::Body) {
self.body = Some(body);
}
fn unset_body(&mut self) {
self.body = None;
}
}
impl HasSourceSpan for MethodDef {
fn with_source_span(self, span: Span) -> Self {
let mut self_mut = self;
self_mut.span = Some(span);
self_mut
}
fn source_span(&self) -> Option<&Span> {
self.span.as_ref()
}
fn set_source_span(&mut self, span: Span) {
self.span = Some(span);
}
fn unset_source_span(&mut self) {
self.span = None;
}
}
impl MethodDef {
pub const fn new(signature: FunctionSignature) -> Self {
Self {
span: None,
signature,
body: None,
annotations: Vec::new(),
}
}
pub fn with_body(self, body: FunctionBody) -> Self {
Self {
body: Some(body),
..self
}
}
pub fn name(&self) -> &Identifier {
self.signature.name()
}
pub const fn signature(&self) -> &FunctionSignature {
&self.signature
}
pub fn set_signature(&mut self, signature: FunctionSignature) {
self.signature = signature;
}
}