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)
|
project(lily)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
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)
|
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) {
|
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"
|
"data IntList = { Nil, Cons(Int, IntList) }\n"
|
||||||
"defn other x y = { 3 }\n"
|
"defn other x y = { 3 }\n"
|
||||||
"defn add x y = { x + y }\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) {
|
} catch(lily::error& e) {
|
||||||
std::cout << e.message << std::endl;
|
std::cout << e.message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,10 +95,10 @@ namespace lily {
|
||||||
|
|
||||||
pgs_tree* patterns = PGS_TREE_NT_CHILD(*tree, 2);
|
pgs_tree* patterns = PGS_TREE_NT_CHILD(*tree, 2);
|
||||||
while(PGS_TREE_NT_COUNT(*patterns) > 1) {
|
while(PGS_TREE_NT_COUNT(*patterns) > 1) {
|
||||||
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));
|
||||||
patterns = PGS_TREE_NT_CHILD(*tree, 2);
|
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;
|
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>
|
#include <vector>
|
||||||
|
|
||||||
namespace lily {
|
namespace lily {
|
||||||
|
class type_manager;
|
||||||
|
class type_env;
|
||||||
|
struct type;
|
||||||
|
|
||||||
struct pattern {
|
struct pattern {
|
||||||
virtual ~pattern() = default;
|
virtual ~pattern() = default;
|
||||||
|
virtual type* check_modifying(type_manager& mgr, std::shared_ptr<type_env> env) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unique_ptr<pattern> pattern_ptr;
|
typedef std::unique_ptr<pattern> pattern_ptr;
|
||||||
|
@ -16,6 +21,7 @@ namespace lily {
|
||||||
pattern_var(std::string n) :
|
pattern_var(std::string n) :
|
||||||
name(std::move(n)) {}
|
name(std::move(n)) {}
|
||||||
~pattern_var() = default;
|
~pattern_var() = default;
|
||||||
|
type* check_modifying(type_manager& mgr, std::shared_ptr<type_env> env);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pattern_cons : pattern {
|
struct pattern_cons : pattern {
|
||||||
|
@ -25,5 +31,6 @@ namespace lily {
|
||||||
pattern_cons(std::string n) :
|
pattern_cons(std::string n) :
|
||||||
name(std::move(n)) {}
|
name(std::move(n)) {}
|
||||||
~pattern_cons() = default;
|
~pattern_cons() = default;
|
||||||
|
type* check_modifying(type_manager& mgr, std::shared_ptr<type_env> env);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace lily {
|
||||||
struct type {
|
struct type {
|
||||||
virtual ~type() = default;
|
virtual ~type() = default;
|
||||||
virtual bool unify_with(type* other) = 0;
|
virtual bool unify_with(type* other) = 0;
|
||||||
|
virtual int arity() { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct type_internal : type {
|
struct type_internal : type {
|
||||||
|
@ -49,6 +50,7 @@ namespace lily {
|
||||||
type_func(type* l, type* r) :
|
type_func(type* l, type* r) :
|
||||||
left(l), right(r) {}
|
left(l), right(r) {}
|
||||||
bool unify_with(type* other);
|
bool unify_with(type* other);
|
||||||
|
int arity() { return right->arity() + 1; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user