Implement constructors type checking (?).

This commit is contained in:
Danila Fedorin 2019-06-09 21:25:02 -07:00
parent 0b80ce711d
commit d729611486
7 changed files with 74 additions and 6 deletions

View File

@ -2,5 +2,5 @@ cmake_minimum_required(VERSION 3.0)
project(lily)
set(CMAKE_CXX_STANDARD 14)
add_executable(lily src/main.cpp src/parser.cpp src/parser.c src/type.cpp src/type_manager.cpp src/ast.cpp src/type_checker.cpp)
add_executable(lily src/main.cpp src/parser.cpp src/parser.c src/type.cpp src/type_manager.cpp src/ast.cpp src/type_checker.cpp src/pattern.cpp)
target_include_directories(lily PUBLIC src)

View File

@ -65,6 +65,32 @@ namespace lily {
}
type* ast_case::check(type_manager& mgr, std::shared_ptr<type_env> env) {
throw error("unimplemented");
type* ctype = of->check(mgr, env);
type* pattern_type = nullptr;
type* branch_type = nullptr;
for(auto& branch : branches) {
auto new_env = std::make_shared<type_env>();
new_env->set_parent(env.get());
type* new_type = branch.pattern->check_modifying(mgr, new_env);
if(!pattern_type) {
pattern_type = new_type;
} else {
if(!pattern_type->unify_with(new_type))
throw error("incompatible pattern types");
}
if(!pattern_type->unify_with(ctype))
throw error("pattern type doesn't match case value type");
type* new_branch_type = branch.expr->check(mgr, new_env);
if(!branch_type) {
branch_type = new_branch_type;
} else {
if(!branch_type->unify_with(new_branch_type))
throw error("branches have incompatible types");
}
}
return branch_type;
}
}

View File

@ -10,7 +10,8 @@ int main() {
"data IntList = { Nil, Cons(Int, IntList) }\n"
"defn other x y = { 3 }\n"
"defn add x y = { x + y }\n"
"defn ones = { Cons 1 ones }");
"defn ones = { Cons 1 ones }\n"
"defn len l = { case l of { Nil -> { 0 } Cons(x, xs) -> { 1 + len xs } } }");
} catch(lily::error& e) {
std::cout << e.message << std::endl;
}

View File

@ -95,10 +95,10 @@ namespace lily {
pgs_tree* patterns = PGS_TREE_NT_CHILD(*tree, 2);
while(PGS_TREE_NT_COUNT(*patterns) > 1) {
new_pattern->vnames.push_back(tree_str(PGS_TREE_NT_CHILD(*tree, 0), source));
patterns = PGS_TREE_NT_CHILD(*tree, 2);
new_pattern->vnames.push_back(tree_str(PGS_TREE_NT_CHILD(*patterns, 0), source));
patterns = PGS_TREE_NT_CHILD(*patterns, 2);
}
new_pattern->vnames.push_back(tree_str(PGS_TREE_NT_CHILD(*tree, 0), source));
new_pattern->vnames.push_back(tree_str(PGS_TREE_NT_CHILD(*patterns, 0), source));
return ptr;
}
}

32
src/pattern.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "pattern.hpp"
#include "error.hpp"
#include "type_checker.hpp"
#include "type_manager.hpp"
namespace lily {
type* pattern_var::check_modifying(type_manager& mgr, std::shared_ptr<type_env> env) {
type* parameter = mgr.create_type<type_parameter>();
env->set_type(name, parameter);
return parameter;
}
type* pattern_cons::check_modifying(type_manager& mgr, std::shared_ptr<type_env> env) {
type* constructor_type = env->get_identifier_type(name);
int arity = constructor_type->arity();
if(arity != vnames.size())
throw error("invalid number of arguments to constructor");
if(arity == 0) {
return constructor_type;
} else {
type_func* func_type;
type* current = constructor_type;
int index = 0;
while((func_type = dynamic_cast<type_func*>(current))) {
env->set_type(vnames[index++], func_type->left);
current = func_type->right;
}
return current;
}
}
}

View File

@ -4,8 +4,13 @@
#include <vector>
namespace lily {
class type_manager;
class type_env;
struct type;
struct pattern {
virtual ~pattern() = default;
virtual type* check_modifying(type_manager& mgr, std::shared_ptr<type_env> env) = 0;
};
typedef std::unique_ptr<pattern> pattern_ptr;
@ -16,6 +21,7 @@ namespace lily {
pattern_var(std::string n) :
name(std::move(n)) {}
~pattern_var() = default;
type* check_modifying(type_manager& mgr, std::shared_ptr<type_env> env);
};
struct pattern_cons : pattern {
@ -25,5 +31,6 @@ namespace lily {
pattern_cons(std::string n) :
name(std::move(n)) {}
~pattern_cons() = default;
type* check_modifying(type_manager& mgr, std::shared_ptr<type_env> env);
};
}

View File

@ -13,6 +13,7 @@ namespace lily {
struct type {
virtual ~type() = default;
virtual bool unify_with(type* other) = 0;
virtual int arity() { return 0; }
};
struct type_internal : type {
@ -49,6 +50,7 @@ namespace lily {
type_func(type* l, type* r) :
left(l), right(r) {}
bool unify_with(type* other);
int arity() { return right->arity() + 1; }
};
}