diff --git a/README.md b/README.md index 3d1594f..f21a9d2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ * [x] No tmps for literals inside of constructors * [x] Fix recursive trait (AsString with prints) * [x] Fix references in traits test +* [x] Fix self mapping --- ### Current task * [ ] Printable trait should take references diff --git a/ppl/src/core.ppl b/ppl/src/core.ppl index 054aa78..8db7dd3 100644 --- a/ppl/src/core.ppl +++ b/ppl/src/core.ppl @@ -233,3 +233,11 @@ trait Destroy: fn destroy <:&mut Self> //================================= +//================================= +// Clonnable +//================================= +/// Trait for things that can be cloned +trait Clonnable: + fn clone <:&Self> -> Self +//================================= + diff --git a/src/hir/types.rs b/src/hir/types.rs index b399235..835830d 100644 --- a/src/hir/types.rs +++ b/src/hir/types.rs @@ -5,7 +5,7 @@ use std::{ }; use crate::{ - mutability::Mutable, named::Named, semantics::ReplaceSelf, syntax::Identifier, + mutability::Mutable, named::Named, syntax::Identifier, AddSourceLocation, }; @@ -245,12 +245,6 @@ impl Type { } } - /// Map self type to given type - pub fn map_self(mut self, ty: &Type) -> Self { - self.drive_mut(&mut ReplaceSelf::with(ty.clone())); - self - } - /// Is this a builtin type? pub fn is_builtin(&self) -> bool { match self { diff --git a/src/semantics/contexts/builtin.rs b/src/semantics/contexts/builtin.rs index 9521a07..4c4f41d 100644 --- a/src/semantics/contexts/builtin.rs +++ b/src/semantics/contexts/builtin.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::hir::{SpecializeParameters, Type}; +use crate::hir::{SpecializeParameters, Trait, Type}; use super::Context; @@ -23,6 +23,41 @@ impl<'ctx> BuiltinContext<'ctx> { context: self.context, } } + + /// Get builtin traits + pub fn traits(&self) -> BuiltinTraits<'ctx> { + BuiltinTraits { + context: self.context, + } + } +} + +/// Helper struct to get builtin traits +pub struct BuiltinTraits<'ctx> { + /// Builtin module + context: &'ctx dyn Context, +} + +/// Helper macro to add builtin traits +macro_rules! builtin_traits { + ($($name: ident),*) => { + $(pub fn $name(&self) -> Trait { + let name = stringify!($name); + self.get_trait(&format!("{}{}", name[0..1].to_uppercase(), &name[1..])) + })* + }; +} + +impl BuiltinTraits<'_> { + /// Get builtin trait by name + fn get_trait(&self, name: &str) -> Trait { + self.context + .find_type(name) + .expect(&format!("Builtin trait `{name}` should be present")) + .as_trait() + } + + builtin_traits!(clonnable); } /// Helper struct to get builtin types @@ -46,7 +81,7 @@ impl BuiltinTypes<'_> { fn get_type(&self, name: &str) -> Type { self.context .find_type(name) - .expect(format!("Builtin type `{name}` should be present",).as_str()) + .expect(&format!("Builtin type `{name}` should be present")) } builtin_types!(none, bool, integer, rational, string, reference, i32, f64); diff --git a/src/semantics/contexts/context.rs b/src/semantics/contexts/context.rs index 2c5e1ae..06dd401 100644 --- a/src/semantics/contexts/context.rs +++ b/src/semantics/contexts/context.rs @@ -2,11 +2,11 @@ use std::fmt::Display; use crate::{ compilation::Compiler, - hir::{Function, FunctionData, FunctionNamePart, ModuleData, Type, Typed}, - semantics::{AddDeclaration, ConvertibleTo, FindDeclaration}, + hir::{Function, FunctionData, FunctionNamePart, ModuleData, SelfType, Type, Typed}, + semantics::{AddDeclaration, ConvertibleTo, FindDeclaration, Implements}, }; -use super::BuiltinContext; +use super::{BuiltinContext, GenericContext}; use crate::DataHolder; @@ -56,41 +56,48 @@ pub trait Context: FindDeclaration + AddDeclaration + Display { } /// Find concrete function for trait function - fn find_implementation(&mut self, trait_fn: &FunctionData, self_type: &Type) -> Option + fn find_implementation( + &mut self, + trait_fn: &FunctionData, + self_type_specialization: Option, + ) -> Option where Self: Sized, { - let funcs = self.functions_with_n_name_parts(trait_fn.name_parts().len()); - funcs - .iter() - .find(|f| { - trait_fn - .name_parts() - .iter() - .zip(f.read().unwrap().name_parts()) - .all(|(a, b)| match (a, b) { - (FunctionNamePart::Text(a), FunctionNamePart::Text(b)) => { - a.as_str() == b.as_str() - } - (FunctionNamePart::Parameter(a), FunctionNamePart::Parameter(b)) => a - .ty() - .map_self(self_type) - .clone() - .convertible_to(b.ty()) - .within(self) - .is_ok_and(|converible| converible), - _ => false, - }) - && trait_fn - .return_type - .clone() - .map_self(self_type) - // TODO: real return type range - .convertible_to(f.read().unwrap().return_type.clone()) - .within(self) - .is_ok_and(|convertible| convertible) - }) - .cloned() + let self_ty: Type = SelfType { + associated_trait: trait_fn.tr.clone().unwrap(), + } + .into(); + let mut context = GenericContext::for_generics(vec![self_ty.clone()], self); + if let Some(concrete) = self_type_specialization.clone() { + context.map_generic(self_ty, concrete); + } + let funcs = context.functions_with_n_name_parts(trait_fn.name_parts().len()); + funcs.into_iter().find(|f| { + let params_ok = trait_fn + .name_parts() + .iter() + .zip(f.read().unwrap().name_parts()) + .all(|(a, b)| match (a, b) { + (FunctionNamePart::Text(a), FunctionNamePart::Text(b)) => { + a.as_str() == b.as_str() + } + (FunctionNamePart::Parameter(a), FunctionNamePart::Parameter(b)) => a + .ty() + .convertible_to(b.ty()) + .within(&mut context) + .is_ok_and(|converible| converible), + _ => false, + }); + let ret_ok = trait_fn + .return_type + // TODO: real return type range + .convertible_to(f.read().unwrap().return_type.clone()) + .within(&mut context) + .is_ok_and(|convertible| convertible); + + params_ok && ret_ok + }) } /// Find destructor for type @@ -108,9 +115,15 @@ pub trait Context: FindDeclaration + AddDeclaration + Display { where Self: Sized, { - let ty = self.builtin().types().reference_to(ty); - let name = format!("clone <:{ty}>"); - self.function_with_name(&name) + match ty { + Type::Class(c) => c + .implements(self.builtin().traits().clonnable()) + .within(self) + .ok()? + .into_iter() + .next(), + _ => None, + } } /// Debug function to print hierarchy of contexts diff --git a/src/semantics/implements.rs b/src/semantics/implements.rs index ecfc17a..12b5e19 100644 --- a/src/semantics/implements.rs +++ b/src/semantics/implements.rs @@ -45,7 +45,7 @@ impl ImplementsCheck<'_, hir::Class> { } if let Some(imp) = - context.find_implementation(&f.read().unwrap(), &Type::from(self.ty.clone())) + context.find_implementation(&f.read().unwrap(), Some(Type::from(self.ty.clone()))) { implemented.push(imp); continue; diff --git a/src/semantics/link_impls.rs b/src/semantics/link_impls.rs index 0764c9d..a7a12d9 100644 --- a/src/semantics/link_impls.rs +++ b/src/semantics/link_impls.rs @@ -2,7 +2,7 @@ use derive_visitor::{DriveMut, VisitorMut}; use log::debug; use crate::{ - hir::{Call, FunctionData, Generic, ModuleData, Type}, + hir::{Call, FunctionData, Generic, ModuleData}, semantics::{GenericContext, Monomorphize}, DataHolder, }; @@ -31,10 +31,10 @@ impl<'ctx, C: Context> TraitFunctionsLinker<'ctx, C> { } debug!(target: "linking-trait-fn-from", "{f}"); - // Unknown type here is ok, because we don't have selfs any more + // Don't have selfs any more so no need to specialize it let mut real_impl = self .context - .find_implementation(&f, &Type::Unknown) + .find_implementation(&f, None) .unwrap() .read() .unwrap()