Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
Fix self mapping. Find clone function by checking trait (#161)
Browse files Browse the repository at this point in the history
* Add Clonnable trait

* Add builtin trait access

* Extract clone function using implementation check

* Update Clonnable

* Fix self mapping

* Fix warnings
  • Loading branch information
gavrilikhin-d authored May 12, 2024
1 parent 1dc52ea commit e0e2177
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 51 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions ppl/src/core.ppl
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,11 @@ trait Destroy:
fn destroy <:&mut Self>
//=================================

//=================================
// Clonnable
//=================================
/// Trait for things that can be cloned
trait Clonnable:
fn clone <:&Self> -> Self
//=================================

8 changes: 1 addition & 7 deletions src/hir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
};

use crate::{
mutability::Mutable, named::Named, semantics::ReplaceSelf, syntax::Identifier,
mutability::Mutable, named::Named, syntax::Identifier,
AddSourceLocation,
};

Expand Down Expand Up @@ -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 {
Expand Down
39 changes: 37 additions & 2 deletions src/semantics/contexts/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt::Display;

use crate::hir::{SpecializeParameters, Type};
use crate::hir::{SpecializeParameters, Trait, Type};

use super::Context;

Expand All @@ -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
Expand All @@ -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);
Expand Down
89 changes: 51 additions & 38 deletions src/semantics/contexts/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<Function>
fn find_implementation(
&mut self,
trait_fn: &FunctionData,
self_type_specialization: Option<Type>,
) -> Option<Function>
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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/semantics/implements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions src/semantics/link_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit e0e2177

Please sign in to comment.