stared redo

This commit is contained in:
2025-08-11 22:17:34 -06:00
parent 1c08ce3a0c
commit 491cf29e68
9 changed files with 167 additions and 171 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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<TraitItem>,
}
#[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),
}

View File

@@ -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 = {
<fd:FunctionDeclaration> ";" => ast::TraitItem::FunctionDeclaration(fd),
<f:Function> => ast::TraitItem::Function(f),
};
pub TraitTypeDeclaration: ast::TraitTypeDeclaration = {
@@ -297,7 +292,6 @@ pub TraitTypeDeclaration: ast::TraitTypeDeclaration = {
pub TypeDeclaration: ast::TypeDeclaration = {
<s:StructTypeDeclaration> => ast::TypeDeclaration::Struct(s),
<a:AliasTypeDeclaration> => ast::TypeDeclaration::Alias(a),
<t:TraitTypeDeclaration> => ast::TypeDeclaration::Trait(t),
};

View File

@@ -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()),

View File

@@ -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);

View File

@@ -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,14 +133,14 @@ 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 found == false {
return Err(errors::TypingError::FunctionNotInTrait {
function_name: impl_function.declaration.name.clone(),

View File

@@ -19,10 +19,10 @@ fn type_meets_trait_bounds(ctx: &Context, type_: &ast::TypeUsage, bounds: &Vec<a
ast::TypeUsage::Named(named) => 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<a
if found == false {
return false;
}
},
}
_ => {
panic!("type is a variable, this should not happen");
}
@@ -57,31 +57,31 @@ 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(&param_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(),
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();
},
}
};
}
@@ -90,7 +90,7 @@ impl TypeConstructor {
return TypeConstructor {
generic: declaration.generic.clone(),
type_usage: declaration.to_type(),
}
};
}
fn construct(&self, ctx: &Context, usage: &ast::GenericUsage) -> Result<ast::TypeUsage> {
match usage {
@@ -108,7 +108,7 @@ 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();
@@ -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,14 +187,14 @@ 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 {});
@@ -215,13 +212,20 @@ 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 {
trait_: impl_.trait_.clone(),
@@ -229,7 +233,7 @@ impl EnvType {
});
}
result = EnvType {
generic: ast::Generic{parameters: vec!()},
generic: ast::Generic { parameters: vec![] },
is_a: self.is_a.clone(),
fields: fields,
impls: impls,
@@ -251,7 +255,7 @@ fn create_builtins() -> HashMap<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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<String, NamedEntity> {
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,7 +413,7 @@ 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(),
@@ -417,7 +421,7 @@ fn apply_self(type_name: &str, constructor: &TypeConstructor) -> TypeConstructor
return TypeConstructor {
generic: constructor.generic.clone(),
type_usage: result,
}
};
}
}
_ => {}
@@ -487,6 +491,7 @@ struct Context {
pub current_function_return: Option<ast::TypeUsage>,
pub environment: HashMap<String, NamedEntity>,
pub id_generator: Rc<ast::IdGenerator>,
pub current_self: Option<String>,
}
impl Context {
@@ -506,27 +511,24 @@ impl Context {
let mut ctx = self.clone();
for parameter in generic.parameters.iter() {
let mut env_type = EnvType {
generic: ast::Generic{
parameters: vec!(),
},
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<String, ast::TraitTypeDeclaration>) -> Result<Context> {
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));
if (func.declaration.arguments.len() == 0) {
continue;
}
// 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),
);
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<SubstitutionMap> {
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<Subs
)?,
)?;
}
},
}
_ => {
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();
@@ -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((