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