Implement constructors type checking (?).
This commit is contained in:
parent
0b80ce711d
commit
d729611486
|
@ -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)
|
||||
|
|
28
src/ast.cpp
28
src/ast.cpp
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
32
src/pattern.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user