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

Commit

Permalink
Better way to replace self in traits (#141)
Browse files Browse the repository at this point in the history
* Make it taking

* Make type drivable

* Add test for references in traits

* Add test for reference to none

* Add test for reference to literal

* Better way to replace self
  • Loading branch information
gavrilikhin-d authored Apr 28, 2024
1 parent 498bb01 commit 7309048
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 13 deletions.
15 changes: 13 additions & 2 deletions src/hir/declarations/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ pub struct MemberData {
#[drive(skip)]
pub name: Identifier,
/// Member's type
#[drive(skip)]
pub ty: Type,
}

Expand Down Expand Up @@ -311,18 +310,30 @@ impl Ranged for Class {
}
}

impl DriveMut for Class {
fn drive_mut<V: derive_visitor::VisitorMut>(&mut self, visitor: &mut V) {
derive_visitor::VisitorMut::visit(visitor, self, ::derive_visitor::Event::Enter);
self.write().unwrap().drive_mut(visitor);
derive_visitor::VisitorMut::visit(visitor, self, ::derive_visitor::Event::Exit);
}
}

/// Declaration of a type
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
#[derive(Debug, PartialEq, Eq, Hash, Clone, DriveMut)]
pub struct ClassData {
/// Keyword `type`
#[drive(skip)]
pub keyword: Keyword<"type">,
/// Type's name
#[drive(skip)]
pub basename: Identifier,
/// Base generic type, if this is a specialization
#[drive(skip)]
pub specialization_of: Option<Class>,
/// Generic parameters of type
pub generic_parameters: Vec<Type>,
/// Kind of a builtin type, if it is a builtin class
#[drive(skip)]
pub builtin: Option<BuiltinClass>,
/// Members of type
pub members: Vec<Member>,
Expand Down
27 changes: 17 additions & 10 deletions src/hir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,27 @@ use std::{
fmt::{Debug, Display},
};

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

use super::{Basename, BuiltinClass, Class, Generic, Member, Trait, TypeReference};
use derive_more::{Display, From, TryInto};
use derive_visitor::DriveMut;
use enum_dispatch::enum_dispatch;

use super::Expression;

/// PPL's Function type
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
#[derive(Debug, PartialEq, Eq, Hash, Clone, DriveMut)]
pub struct FunctionType {
/// Parameters
pub parameters: Vec<Type>,
/// Return type
pub return_type: Box<Type>,
/// Cached name of function type
#[drive(skip)]
name: String,
}

Expand Down Expand Up @@ -94,9 +99,10 @@ impl FunctionTypeBuilder {
}

/// Self type is used to represent type of self in trait methods
#[derive(Debug, Clone)]
#[derive(Debug, Clone, DriveMut)]
pub struct SelfType {
/// Trait associated with self type
#[drive(skip)]
pub associated_trait: Trait,
}

Expand Down Expand Up @@ -126,13 +132,16 @@ impl Display for SelfType {
}

/// Type of a generic parameter
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, DriveMut)]
pub struct GenericType {
/// Name of the generic type
#[drive(skip)]
pub name: Identifier,
/// Is this generic type generated by compiler?
#[drive(skip)]
pub generated: bool,
/// Constraint for this type
#[drive(skip)]
pub constraint: Option<TypeReference>,
}

Expand Down Expand Up @@ -161,7 +170,7 @@ impl Display for GenericType {
}

/// Type of values
#[derive(Debug, Display, PartialEq, Eq, Hash, Clone, From, TryInto)]
#[derive(Debug, Display, PartialEq, Eq, Hash, Clone, From, TryInto, DriveMut)]
pub enum Type {
/// User defined type
Class(Class),
Expand Down Expand Up @@ -235,11 +244,9 @@ impl Type {
}

/// Map self type to given type
pub fn map_self<'s>(&'s self, ty: &'s Type) -> &'s Type {
match self {
Type::SelfType(_) => ty,
_ => self,
}
pub fn map_self(mut self, ty: &Type) -> Self {
self.drive_mut(&mut ReplaceSelf::with(ty.clone()));
self
}

/// Is this a builtin type?
Expand Down
2 changes: 1 addition & 1 deletion src/semantics/contexts/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ pub trait Context: FindDeclaration + AddDeclaration + Display {
})
&& trait_fn
.return_type
.map_self(self_type)
.clone()
.map_self(self_type)
// TODO: real return type range
.convertible_to(f.read().unwrap().return_type.clone())
.within(self)
Expand Down
3 changes: 3 additions & 0 deletions src/semantics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ pub use tmp::*;

mod unnamed;
pub use unnamed::*;

mod replace_self;
pub use replace_self::*;
21 changes: 21 additions & 0 deletions src/semantics/replace_self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use derive_visitor::VisitorMut;

use crate::hir::Type;

#[derive(VisitorMut)]
#[visitor(Type(enter))]
pub struct ReplaceSelf {
ty: Type,
}

impl ReplaceSelf {
pub fn with(ty: Type) -> Self {
Self { ty }
}

fn enter_type(&mut self, ty: &mut Type) {
if let Type::SelfType(_) = ty {
*ty = self.ty.clone();
}
}
}
3 changes: 3 additions & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ e2es! {
predeclare_vars,
rational,
reference_mut,
reference_to_literal,
reference_to_none,
references,
specify_variable_ty,
star,
string,
supertraits,
traits,
type_as_value,
trait_with_ref,
type_of,
wrong_initializer_type
}
Expand Down
3 changes: 3 additions & 0 deletions src/tests/reference_to_literal/src/main.ppl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn foo <x: &Integer> => println x

foo 42
4 changes: 4 additions & 0 deletions src/tests/reference_to_none/src/main.ppl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn foo <:&None> => println "foo"

let x = none
foo x
9 changes: 9 additions & 0 deletions src/tests/trait_with_ref/src/main.ppl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
trait Foo:
fn foo <:&Self>

fn foo <:&Integer> => println "foo integer"

fn bar <x: &Foo> => foo x

let x = 0
bar x

0 comments on commit 7309048

Please sign in to comment.