diff --git a/Dockerfile b/Dockerfile index 3af2e60..57c8b8e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM rust:1.54 +FROM rust:1.89 -RUN apt update && apt-get install -y llvm clang +# RUN apt update && apt-get install -y llvm clang RUN rustup component add rustfmt WORKDIR /code diff --git a/README.md b/README.md index 25694a6..def87dc 100644 --- a/README.md +++ b/README.md @@ -43,13 +43,13 @@ This language is under active development, progress will be marked here as the l - [x] Basic - [ ] Inferred - [ ] Higher kinded types - - [ ] Variadic generic types - [ ] Control Flow - [x] If - [ ] While - [ ] For - [ ] IO - [ ] Enums + - [ ] Errors - [ ] Lambdas - [ ] Imports - [ ] Visibility diff --git a/examples/main.bl b/examples/main.bl index e901eae..8b0f472 100644 --- a/examples/main.bl +++ b/examples/main.bl @@ -81,16 +81,17 @@ fn main(): i64 { type TestTrait trait { fn class_method(id: i64): Self; fn instance_method(self: Self): i64; - fn default_impl(self: Self): i64 { - return self.instance_method(); - } + fn default_impl(self: Self): i64; } impl TestTrait for User { fn class_method(id: i64): Self { - return User{id: id,}; + return Self{id: id,}; } fn instance_method(self: Self): i64 { return self.get_id(); } + fn default_impl(self: Self): i64 { + return self.instance_method(); + } } diff --git a/src/ast.rs b/src/ast.rs index a2d63ca..a2cf07b 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::{cell::RefCell, clone}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct IdGenerator { @@ -8,7 +8,10 @@ pub struct IdGenerator { impl IdGenerator { pub fn new(key: &str) -> Self { - IdGenerator { id_key: key.to_string(), counter: RefCell::new(0) } + IdGenerator { + id_key: key.to_string(), + counter: RefCell::new(0), + } } pub fn next(&self) -> String { @@ -72,8 +75,7 @@ pub struct UnknownTypeUsage { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum NamespaceTypeUsage { - Type(NamedTypeUsage) - // Module + Type(NamedTypeUsage), // Module } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -81,7 +83,7 @@ pub enum TypeUsage { Function(FunctionTypeUsage), Named(NamedTypeUsage), Unknown(UnknownTypeUsage), - Namespace(NamespaceTypeUsage) + Namespace(NamespaceTypeUsage), } impl TypeUsage { @@ -114,6 +116,30 @@ impl TypeUsage { return_type: Box::new(TypeUsage::new_unknown(&id_gen)), }); } + + pub fn replace_type(&self, old: &str, new: &Identifier) -> TypeUsage { + return match &self { + TypeUsage::Function(function) => { + return TypeUsage::Function(FunctionTypeUsage { + arguments: function.arguments.iter().map(|arg| arg.replace_type(old, new)).collect(), + return_type: Box::new(function.return_type.replace_type(old, new)), + }); + } + TypeUsage::Named(named) => { + let name = if (named.name.name.value == old) { + new.clone() + } else { + named.name.clone() + }; + return TypeUsage::Named(NamedTypeUsage { + type_parameters: named.type_parameters.clone(), + name: name, + }); + } + TypeUsage::Namespace(namespace) => return TypeUsage::Namespace(namespace.clone()), + TypeUsage::Unknown(unkown) => return TypeUsage::Unknown(unkown.clone()), + }; + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -347,7 +373,6 @@ pub struct StructTypeDeclaration { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TraitItem { FunctionDeclaration(FunctionDeclaration), - Function(Function), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -357,17 +382,10 @@ pub struct TraitTypeDeclaration { pub functions: Vec, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct AliasTypeDeclaration { - pub name: Identifier, - pub replaces: TypeUsage, -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeDeclaration { Struct(StructTypeDeclaration), Primitive(PrimitiveTypeDeclaration), - Alias(AliasTypeDeclaration), Trait(TraitTypeDeclaration), } diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop index 3b5f5ad..47a16d0 100644 --- a/src/grammar.lalrpop +++ b/src/grammar.lalrpop @@ -281,13 +281,8 @@ pub StructTypeDeclaration: ast::StructTypeDeclaration = { } }; -pub AliasTypeDeclaration: ast::AliasTypeDeclaration = { - "type" "=" ";" => ast::AliasTypeDeclaration{name: i, replaces: t} -}; - pub TraitItem: ast::TraitItem = { ";" => ast::TraitItem::FunctionDeclaration(fd), - => ast::TraitItem::Function(f), }; pub TraitTypeDeclaration: ast::TraitTypeDeclaration = { @@ -297,7 +292,6 @@ pub TraitTypeDeclaration: ast::TraitTypeDeclaration = { pub TypeDeclaration: ast::TypeDeclaration = { => ast::TypeDeclaration::Struct(s), - => ast::TypeDeclaration::Alias(a), => ast::TypeDeclaration::Trait(t), }; diff --git a/src/interpreter.rs b/src/interpreter.rs index aa49d6b..d6968e0 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -87,12 +87,6 @@ impl Context { NamedEntity::TypeDeclaration(ast::TypeDeclaration::Struct(struct_.clone())), ); } - ast::ModuleItem::TypeDeclaration(ast::TypeDeclaration::Alias(alias)) => { - ctx.environment.insert( - alias.name.name.value.to_string(), - NamedEntity::TypeDeclaration(ast::TypeDeclaration::Alias(alias.clone())), - ); - } ast::ModuleItem::Function(function) => { ctx.environment.insert( function.declaration.name.name.value.to_string(), @@ -418,6 +412,9 @@ impl TreeWalkInterpreter { } } ast::Subexpression::VariableUsage(variable_usage) => { + if !ctx.environment.contains_key(&variable_usage.name.name.value) { + panic!(variable_usage.name.name.value.clone()); + } let variable_value = match &ctx.environment[&variable_usage.name.name.value] { NamedEntity::Variable(v) => v.clone(), _ => panic!("variable lookup of type"), @@ -469,7 +466,7 @@ impl TreeWalkInterpreter { if method.declaration.arguments.len() > 0 { match &method.declaration.arguments[0].type_ { ast::TypeUsage::Named(arg_named) => { - if arg_named.name.name.value == s.source.name.name.value { + if arg_named.name.name.value == "Self" { return ExpressionResult::Value(Value::Function(Function { partial: vec![source.clone()], ref_: FunctionRef::User(method.clone()), diff --git a/src/main.rs b/src/main.rs index bcbfd4a..800cbc8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,6 @@ mod ast; mod errors; mod interpreter; mod trait_checking; -mod type_alias_resolution; mod type_checking; #[macro_use] extern crate lalrpop_util; @@ -19,7 +18,7 @@ fn main() { let matches = App::new("Boring Language Compiler") .version("0.0.1") .author("Andrew Segavac") - .about("Compiles boring language files to LLVM IR.") + .about("Compiles boringlang files") .arg( Arg::with_name("OUTPUT") .short("o") @@ -40,26 +39,18 @@ fn main() { let unknown_id_gen = ast::IdGenerator::new("S"); let module_ast = grammar::ModuleParser::new().parse(&unknown_id_gen, &contents).unwrap(); //TODO: convert to error // println!("ast: {:#?}", &module_ast); - let alias_resolver = type_alias_resolution::TypeAliasResolver {}; - let resolved_ast = match alias_resolver.with_module(&module_ast) { - Ok(r) => r, - Err(err) => { - println!("type checking error: {:#?}", &err); - panic!("bad alias"); - } - }; // println!("resolved ast: {:#?}", &resolved_ast); let trait_checker = trait_checking::TraitChecker {}; - match trait_checker.with_module(&resolved_ast) { + match trait_checker.with_module(&module_ast) { Ok(_) => {} Err(err) => { - println!("type checking error: {:#?}", &err); + println!("trait checking error: {:#?}", &err); return; } } let type_checker = type_checking::TypeChecker {}; - let type_checking_result = type_checker.with_module(&resolved_ast); + let type_checking_result = type_checker.with_module(&module_ast); match &type_checking_result { Ok((checked_ast, subst)) => { println!("checked ast: {:#?}", &checked_ast); diff --git a/src/trait_checking.rs b/src/trait_checking.rs index 77a9a7d..731f27f 100644 --- a/src/trait_checking.rs +++ b/src/trait_checking.rs @@ -23,9 +23,7 @@ fn compare_struct_trait( match struct_ { ast::TypeUsage::Named(named) => match trait_ { ast::TypeUsage::Named(trait_named) => { - if named.name.name.value == trait_named.name.name.value - || (named.name.name.value == struct_name.name.value && trait_named.name.name.value == trait_name.name.value) - { + if named.name.name.value == trait_named.name.name.value { return Ok(()); } return Err(errors::TypingError::TypeMismatch { @@ -128,19 +126,6 @@ impl TraitChecker { }); } } - ast::TraitItem::Function(function) => { - // skip found check because it has a default - for impl_function in impl_.functions.iter() { - if impl_function.declaration.name.name.value == function.declaration.name.name.value { - compare_struct_trait( - &impl_function.declaration.to_type(), - &function.declaration.to_type(), - &impl_.struct_.name, - &trait_.name, - )?; - } - } - } } } // assert all functions are in trait @@ -148,13 +133,13 @@ impl TraitChecker { let mut found = false; for trait_item in trait_declaration.functions.iter() { let declaration = match trait_item { - ast::TraitItem::Function(function) => &function.declaration, - ast::TraitItem::FunctionDeclaration(declaration) => &declaration, + ast::TraitItem::FunctionDeclaration(declaration) => { + if impl_function.declaration.name.name.value == declaration.name.name.value { + found = true; + break; + } + } }; - if impl_function.declaration.name.name.value == declaration.name.name.value { - found = true; - break; - } } if found == false { return Err(errors::TypingError::FunctionNotInTrait { diff --git a/src/type_checking.rs b/src/type_checking.rs index 35e5cc3..3e9ad7f 100644 --- a/src/type_checking.rs +++ b/src/type_checking.rs @@ -19,10 +19,10 @@ fn type_meets_trait_bounds(ctx: &Context, type_: &ast::TypeUsage, bounds: &Vec named, ast::TypeUsage::Function(_) => { return false; - }, + } ast::TypeUsage::Unknown(_) => { return true; // unknown this pass, skip, test once known - }, + } ast::TypeUsage::Namespace(_) => { panic!("impossible"); } @@ -39,7 +39,7 @@ fn type_meets_trait_bounds(ctx: &Context, type_: &ast::TypeUsage, bounds: &Vec { panic!("type is a variable, this should not happen"); } @@ -57,47 +57,47 @@ fn replace_generic_with_concrete(replace: &ast::Identifier, with_type: &ast::Typ } result.type_parameters = match &named.type_parameters { ast::GenericUsage::Known(known) => { - let mut param_result = vec!(); + let mut param_result = vec![]; for param in known.parameters.iter() { param_result.push(replace_generic_with_concrete(replace, with_type, param)); } ast::GenericUsage::new(¶m_result) - }, - ast::GenericUsage::Unknown => { - ast::GenericUsage::Unknown - }, + } + ast::GenericUsage::Unknown => ast::GenericUsage::Unknown, }; return ast::TypeUsage::Named(result); - }, + } ast::TypeUsage::Function(func) => { - let result = ast::TypeUsage::Function(ast::FunctionTypeUsage{ - arguments: func.arguments.iter().map(|arg| { - replace_generic_with_concrete(replace, with_type, arg) - }).collect(), + let result = ast::TypeUsage::Function(ast::FunctionTypeUsage { + arguments: func + .arguments + .iter() + .map(|arg| replace_generic_with_concrete(replace, with_type, arg)) + .collect(), return_type: Box::new(replace_generic_with_concrete(replace, with_type, &func.return_type)), }); return result; - }, + } _ => { // in_type is unknown, skip return in_type.clone(); - }, + } }; } impl TypeConstructor { fn from_declaration(declaration: &ast::FunctionDeclaration) -> TypeConstructor { - return TypeConstructor{ + return TypeConstructor { generic: declaration.generic.clone(), type_usage: declaration.to_type(), - } + }; } fn construct(&self, ctx: &Context, usage: &ast::GenericUsage) -> Result { match usage { ast::GenericUsage::Known(known_usage) => { let mut result = self.type_usage.clone(); if known_usage.parameters.len() != self.generic.parameters.len() { - return Err(errors::TypingError::WrongNumberOfTypeParameters{}); + return Err(errors::TypingError::WrongNumberOfTypeParameters {}); } // 1. for arg in args, assert arg matches self.generic traits via impl name // 2. replace type usage names with arg types @@ -108,13 +108,13 @@ impl TypeConstructor { result = replace_generic_with_concrete(&self.generic.parameters[i].name, &known_usage.parameters[i], &self.type_usage); } return Ok(result); - }, + } ast::GenericUsage::Unknown => { // generate new Unknown Types for matching let mut result = self.type_usage.clone(); for param in self.generic.parameters.iter() { let id = ctx.id_generator.next(); - let unknown = ast::TypeUsage::Unknown(ast::UnknownTypeUsage{name: id}); + let unknown = ast::TypeUsage::Unknown(ast::UnknownTypeUsage { name: id }); result = replace_generic_with_concrete(¶m.name, &unknown, &self.type_usage); } return Ok(result); @@ -165,9 +165,6 @@ impl EnvType { ast::TraitItem::FunctionDeclaration(fd) => { functions.insert(fd.name.name.value.to_string(), TypeConstructor::from_declaration(&fd)); } - ast::TraitItem::Function(f) => { - functions.insert(f.declaration.name.name.value.to_string(), TypeConstructor::from_declaration(&f.declaration)); - } } } let impl_ = EnvImpl { @@ -190,17 +187,17 @@ impl EnvType { let known_usage = match usage { ast::GenericUsage::Known(known) => known.clone(), ast::GenericUsage::Unknown => { - let mut new_unknowns = vec!(); + let mut new_unknowns = vec![]; for _ in 0..self.generic.parameters.len() { new_unknowns.push(ast::TypeUsage::new_unknown(&ctx.id_generator)); } ast::GenericInstantiation { parameters: new_unknowns.iter().map(|tp| tp.clone()).collect(), } - }, + } }; if known_usage.parameters.len() != self.generic.parameters.len() { - return Err(errors::TypingError::WrongNumberOfTypeParameters{}); + return Err(errors::TypingError::WrongNumberOfTypeParameters {}); } for i in 0..known_usage.parameters.len() { if !type_meets_trait_bounds(ctx, &known_usage.parameters[i], &self.generic.parameters[i].bounds) { @@ -215,21 +212,28 @@ impl EnvType { let type_usage = replace_generic_with_concrete(&self.generic.parameters[i].name, &known_usage.parameters[i], &v); fields.insert(k.clone(), type_usage); } - let mut impls = vec!(); + let mut impls = vec![]; for impl_ in result.impls.iter() { let mut functions = HashMap::new(); for (name, func) in impl_.functions.iter() { - let type_usage = replace_generic_with_concrete(&self.generic.parameters[i].name, &known_usage.parameters[i], &func.type_usage); + let type_usage = + replace_generic_with_concrete(&self.generic.parameters[i].name, &known_usage.parameters[i], &func.type_usage); - functions.insert(name.clone(), TypeConstructor{generic: func.generic.clone(), type_usage: type_usage}); + functions.insert( + name.clone(), + TypeConstructor { + generic: func.generic.clone(), + type_usage: type_usage, + }, + ); } - impls.push(EnvImpl{ + impls.push(EnvImpl { trait_: impl_.trait_.clone(), functions: functions, }); } - result = EnvType{ - generic: ast::Generic{parameters: vec!()}, + result = EnvType { + generic: ast::Generic { parameters: vec![] }, is_a: self.is_a.clone(), fields: fields, impls: impls, @@ -251,7 +255,7 @@ fn create_builtins() -> HashMap { result.insert( "i8".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -260,7 +264,7 @@ fn create_builtins() -> HashMap { result.insert( "i16".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -269,7 +273,7 @@ fn create_builtins() -> HashMap { result.insert( "i32".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -278,7 +282,7 @@ fn create_builtins() -> HashMap { result.insert( "i64".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -287,7 +291,7 @@ fn create_builtins() -> HashMap { result.insert( "isize".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -297,7 +301,7 @@ fn create_builtins() -> HashMap { result.insert( "u8".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -306,7 +310,7 @@ fn create_builtins() -> HashMap { result.insert( "u16".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -315,7 +319,7 @@ fn create_builtins() -> HashMap { result.insert( "u32".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -324,7 +328,7 @@ fn create_builtins() -> HashMap { result.insert( "u64".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -333,7 +337,7 @@ fn create_builtins() -> HashMap { result.insert( "usize".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -343,7 +347,7 @@ fn create_builtins() -> HashMap { result.insert( "f32".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -352,7 +356,7 @@ fn create_builtins() -> HashMap { result.insert( "f64".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -362,7 +366,7 @@ fn create_builtins() -> HashMap { result.insert( "bool".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -371,7 +375,7 @@ fn create_builtins() -> HashMap { result.insert( "!".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -380,7 +384,7 @@ fn create_builtins() -> HashMap { result.insert( "unit".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -389,7 +393,7 @@ fn create_builtins() -> HashMap { result.insert( "String".to_string(), NamedEntity::NamedType(EnvType { - generic: ast::Generic{parameters: vec!()}, + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Scalar, fields: HashMap::new(), impls: vec![], @@ -409,15 +413,15 @@ fn apply_self(type_name: &str, constructor: &TypeConstructor) -> TypeConstructor if func.arguments.len() > 0 { match &func.arguments[0] { ast::TypeUsage::Named(named) => { - if type_name == named.name.name.value { + if type_name == named.name.name.value || type_name == "Self" { let result = ast::TypeUsage::Function(ast::FunctionTypeUsage { arguments: func.arguments[1..func.arguments.len()].iter().map(|arg| arg.clone()).collect(), return_type: func.return_type.clone(), }); - return TypeConstructor{ + return TypeConstructor { generic: constructor.generic.clone(), type_usage: result, - } + }; } } _ => {} @@ -487,6 +491,7 @@ struct Context { pub current_function_return: Option, pub environment: HashMap, pub id_generator: Rc, + pub current_self: Option, } impl Context { @@ -505,28 +510,25 @@ impl Context { fn add_generic(&self, generic: &ast::Generic) -> Result { let mut ctx = self.clone(); for parameter in generic.parameters.iter() { - let mut env_type = EnvType{ - generic: ast::Generic{ - parameters: vec!(), - }, + let mut env_type = EnvType { + generic: ast::Generic { parameters: vec![] }, is_a: TypeType::Trait, fields: HashMap::new(), - impls: vec!(), + impls: vec![], }; for bound in parameter.bounds.iter() { if !self.environment.contains_key(&bound.name.value) { - return Err(errors::TypingError::TypeDoesNotExist { - identifier: bound.clone(), - }); + return Err(errors::TypingError::TypeDoesNotExist { identifier: bound.clone() }); } match &self.environment[&bound.name.value] { NamedEntity::NamedType(named_type) => { env_type.impls.push(named_type.impls[0].clone()); - }, + } _ => {} } - }; - ctx.environment.insert(parameter.name.name.value.clone(), NamedEntity::NamedType(env_type)); + } + ctx.environment + .insert(parameter.name.name.value.clone(), NamedEntity::NamedType(env_type)); } return Ok(ctx); } @@ -534,31 +536,26 @@ impl Context { fn add_impl(&self, impl_: &ast::Impl, traits: &HashMap) -> Result { let mut functions = HashMap::new(); for func in impl_.functions.iter() { - functions.insert(func.declaration.name.name.value.to_string(), TypeConstructor::from_declaration(&func.declaration)); - } - // fill out defaults - match &impl_.trait_ { - Some(trait_) => { - if !traits.contains_key(&trait_.name.name.value) { - return Err(errors::TypingError::TypeDoesNotExist { - identifier: trait_.name.clone(), - }); - } - for func in traits[&trait_.name.name.value].functions.iter() { - match func { - ast::TraitItem::Function(default_function) => { - if !functions.contains_key(&default_function.declaration.name.name.value) { - functions.insert( - default_function.declaration.name.name.value.to_string(), - TypeConstructor::from_declaration(&default_function.declaration), - ); - } - } - _ => {} + if (func.declaration.arguments.len() == 0) { + continue; + } + match &func.declaration.arguments[0].type_ { + ast::TypeUsage::Named(named) => { + if (named.name.name.value != "Self") { + continue; } } + _ => { + continue; + } } - None => {} + let type_constructor = TypeConstructor::from_declaration(&func.declaration); + let resolved_tc = TypeConstructor { + generic: type_constructor.generic.clone(), + type_usage: type_constructor.type_usage.replace_type(&"Self", &impl_.struct_.name), + }; + // is self function, add to context for this type + functions.insert(func.declaration.name.name.value.to_string(), resolved_tc); } let mut result = self.clone(); let mut env_named = result.environment[&impl_.struct_.name.name.value].clone(); @@ -641,9 +638,7 @@ fn apply_substitution(ctx: &Context, substitution: &SubstitutionMap, type_: &ast ast::TypeUsage::Unknown(unknown.clone()) } } - ast::TypeUsage::Namespace(namespace) => { - ast::TypeUsage::Namespace(namespace.clone()) - } + ast::TypeUsage::Namespace(namespace) => ast::TypeUsage::Namespace(namespace.clone()), ast::TypeUsage::Function(function) => { let mut arguments = vec![]; for arg in function.arguments.iter() { @@ -670,7 +665,10 @@ fn compose_substitutions(ctx: &Context, s1: &SubstitutionMap, s2: &SubstitutionM fn unify(ctx: &Context, t1: &ast::TypeUsage, t2: &ast::TypeUsage) -> Result { match (t1, t2) { (ast::TypeUsage::Named(named1), ast::TypeUsage::Named(named2)) => { - if named1.name.name.value == named2.name.name.value { + if named1.name.name.value == named2.name.name.value + || (named1.name.name.value == "Self" && Some(named2.name.name.value.clone()) == ctx.current_self) + || (named2.name.name.value == "Self" && Some(named1.name.name.value.clone()) == ctx.current_self) + { let mut result = SubstitutionMap::new(); match (&named1.type_parameters, &named2.type_parameters) { (ast::GenericUsage::Known(known1), ast::GenericUsage::Known(known2)) => { @@ -691,10 +689,10 @@ fn unify(ctx: &Context, t1: &ast::TypeUsage, t2: &ast::TypeUsage) -> Result { panic!("should never be unknown") - }, + } } return Ok(result); } @@ -784,6 +782,7 @@ impl TypeChecker { environment: create_builtins(), current_function_return: None, id_generator: Rc::new(ast::IdGenerator::new("T")), + current_self: None, }; let mut traits = HashMap::new(); @@ -810,7 +809,7 @@ impl TypeChecker { }; ctx.environment.insert( function.declaration.name.name.value.to_string(), - NamedEntity::Function(TypeConstructor{ + NamedEntity::Function(TypeConstructor { generic: function.declaration.generic.clone(), type_usage: ast::TypeUsage::Function(function_type), }), @@ -931,9 +930,6 @@ impl TypeChecker { ast::TypeDeclaration::Primitive(primitive) => { return Ok((ast::TypeDeclaration::Primitive(primitive.clone()), SubstitutionMap::new())); } - ast::TypeDeclaration::Alias(alias) => { - return Ok((ast::TypeDeclaration::Alias(alias.clone()), SubstitutionMap::new())); - } ast::TypeDeclaration::Trait(trait_) => { let (result, subst) = self.with_trait_declaration(ctx, incoming_substitutions, trait_)?; return Ok((ast::TypeDeclaration::Trait(result), subst)); @@ -947,7 +943,11 @@ impl TypeChecker { incoming_substitutions: &SubstitutionMap, trait_: &ast::TraitTypeDeclaration, ) -> Result<(ast::TraitTypeDeclaration, SubstitutionMap)> { - let gen_ctx = ctx.add_generic(&trait_.generic)?; + let mut gen_ctx = ctx.add_generic(&trait_.generic)?; + gen_ctx + .environment + .insert("Self".to_string(), gen_ctx.environment[&trait_.name.name.value].clone()); + gen_ctx.current_self = Some(trait_.name.name.value.clone()); let mut substitutions = incoming_substitutions.clone(); let mut result_functions = vec![]; for item in &trait_.functions { @@ -956,11 +956,6 @@ impl TypeChecker { let result_declaration = self.with_function_declaration(&gen_ctx, declaration)?; result_functions.push(ast::TraitItem::FunctionDeclaration(result_declaration)); } - ast::TraitItem::Function(function) => { - let (function_result, susbt) = self.with_function(&gen_ctx, incoming_substitutions, function)?; - substitutions = compose_substitutions(ctx, &substitutions, &susbt)?; - result_functions.push(ast::TraitItem::Function(function_result)); - } } } Ok(( @@ -996,7 +991,11 @@ impl TypeChecker { incoming_substitutions: &SubstitutionMap, impl_: &ast::Impl, ) -> Result<(ast::Impl, SubstitutionMap)> { - let impl_ctx = ctx.add_generic(&impl_.generic)?; + let mut impl_ctx = ctx.add_generic(&impl_.generic)?; + impl_ctx + .environment + .insert("Self".to_string(), impl_ctx.environment[&impl_.struct_.name.name.value].clone()); + impl_ctx.current_self = Some(impl_.struct_.name.name.value.clone()); let mut substitutions = incoming_substitutions.clone(); type_exists( @@ -1459,14 +1458,25 @@ impl TypeChecker { let mut substitution = substitution.clone(); match &ctx.environment[&variable_usage.name.name.value] { NamedEntity::NamedType(named_type) => { - let type_ = ast::TypeUsage::Namespace(ast::NamespaceTypeUsage::Type(ast::NamedTypeUsage{name: variable_usage.name.clone(), type_parameters: variable_usage.type_parameters.clone()})); + let type_ = ast::TypeUsage::Namespace(ast::NamespaceTypeUsage::Type(ast::NamedTypeUsage { + name: variable_usage.name.clone(), + type_parameters: variable_usage.type_parameters.clone(), + })); substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &variable_usage.type_, &type_)?)?; } NamedEntity::Variable(variable) => { substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &variable_usage.type_, &variable)?)?; } NamedEntity::Function(function) => { - substitution = compose_substitutions(ctx, &substitution, &unify(ctx, &variable_usage.type_, &function.construct(ctx, &variable_usage.type_parameters)?)?)?; + substitution = compose_substitutions( + ctx, + &substitution, + &unify( + ctx, + &variable_usage.type_, + &function.construct(ctx, &variable_usage.type_parameters)?, + )?, + )?; } } Ok((