Type check constructors.

This commit is contained in:
Danila Fedorin 2019-06-09 20:24:44 -07:00
parent 0b544a2515
commit 0b80ce711d
8 changed files with 31 additions and 7 deletions

View File

@ -4,17 +4,14 @@
namespace lily { namespace lily {
type* ast_num::check(type_manager& mgr, std::shared_ptr<type_env> env) { type* ast_num::check(type_manager& mgr, std::shared_ptr<type_env> env) {
std::cout << "checking number" << std::endl;
return mgr.require_type("Int"); return mgr.require_type("Int");
} }
type* ast_var::check(type_manager& mgr, std::shared_ptr<type_env> env) { type* ast_var::check(type_manager& mgr, std::shared_ptr<type_env> env) {
std::cout << "checking variable" << std::endl;
return env->get_identifier_type(name); return env->get_identifier_type(name);
} }
type* ast_app::check(type_manager& mgr, std::shared_ptr<type_env> env) { type* ast_app::check(type_manager& mgr, std::shared_ptr<type_env> env) {
std::cout << "checking application" << std::endl;
type* ltype = left->check(mgr, env); type* ltype = left->check(mgr, env);
type* rtype = right->check(mgr, env); type* rtype = right->check(mgr, env);

View File

@ -9,7 +9,8 @@ int main() {
"data Color = { Red, Black }\n" "data Color = { Red, Black }\n"
"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 + add x x }"); "defn add x y = { x + y }\n"
"defn ones = { Cons 1 ones }");
} catch(lily::error& e) { } catch(lily::error& e) {
std::cout << e.message << std::endl; std::cout << e.message << std::endl;
} }

View File

@ -279,6 +279,9 @@ namespace lily {
base_env->set_type(pair.first, current_type); base_env->set_type(pair.first, current_type);
} }
// We also want to gather all the constructor calls.
type_mgr.register_constructors(base_env);
// Now that we have collected the functions, check their bodies. // Now that we have collected the functions, check their bodies.
for(auto& pair : functions) { for(auto& pair : functions) {
type* body_type = type* body_type =

View File

@ -10,7 +10,7 @@ namespace lily {
new_constructor->params = std::move(params); new_constructor->params = std::move(params);
constructor* raw_ptr = new_constructor.get(); constructor* raw_ptr = new_constructor.get();
constructors.push_back(std::move(new_constructor)); constructors[name] = std::move(new_constructor);
return raw_ptr; return raw_ptr;
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
namespace lily { namespace lily {
enum reserved_types { enum reserved_types {
@ -34,7 +35,7 @@ namespace lily {
}; };
int type_id; int type_id;
std::vector<std::unique_ptr<constructor>> constructors; std::map<std::string, std::unique_ptr<constructor>> constructors;
type_data(int id) : type_id(id) {} type_data(int id) : type_id(id) {}
constructor* create_constructor(const std::string& name, std::vector<type*>&& params); constructor* create_constructor(const std::string& name, std::vector<type*>&& params);

View File

@ -7,7 +7,6 @@ namespace lily {
} }
type* type_env::get_identifier_type(const std::string& name) { type* type_env::get_identifier_type(const std::string& name) {
std::cout << "looking up " << name << std::endl;
if(!identifier_types.count(name)) { if(!identifier_types.count(name)) {
if(parent) return parent->get_identifier_type(name); if(parent) return parent->get_identifier_type(name);
throw error("unknown variable"); throw error("unknown variable");

View File

@ -1,6 +1,8 @@
#include "type_manager.hpp" #include "type_manager.hpp"
#include <memory> #include <memory>
#include "error.hpp" #include "error.hpp"
#include "type.hpp"
#include "type_checker.hpp"
namespace lily { namespace lily {
type_manager::type_manager() { type_manager::type_manager() {
@ -38,4 +40,21 @@ namespace lily {
if(!type_names.count(name)) throw error("invalid type name"); if(!type_names.count(name)) throw error("invalid type name");
return type_names.find(name)->second; return type_names.find(name)->second;
} }
void type_manager::register_constructors(std::shared_ptr<type_env> env) {
for(auto& type_ref : types) {
type_data* data_type = dynamic_cast<type_data*>(type_ref.get());
if(!data_type) continue;
for(auto& pair : data_type->constructors) {
size_t param_count = pair.second->params.size();
type* current_type = data_type;
for(int i = 0; i < param_count; i++) {
type* param = pair.second->params[param_count - i - 1];
current_type = create_type<type_func>(param, current_type);
}
env->set_type(pair.first, current_type);
}
}
}
} }

View File

@ -5,6 +5,8 @@
#include "type.hpp" #include "type.hpp"
namespace lily { namespace lily {
class type_env;
class type_manager { class type_manager {
private: private:
int next_id; int next_id;
@ -25,5 +27,7 @@ namespace lily {
} }
type* require_type(const std::string& name) const; type* require_type(const std::string& name) const;
void register_constructors(std::shared_ptr<type_env> env);
}; };
} }