Rewrite types to not use IDs unless needed.

This commit is contained in:
Danila Fedorin 2019-06-09 16:13:13 -07:00
parent f3be325644
commit 1e77622589
8 changed files with 110 additions and 76 deletions

View File

@ -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) add_executable(lily src/main.cpp src/parser.cpp src/parser.c src/type.cpp src/type_manager.cpp)
target_include_directories(lily PUBLIC src) target_include_directories(lily PUBLIC src)

View File

@ -1,12 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include "type.hpp"
namespace lily {
struct constructor {
int parent_type;
int tag;
std::vector<std::weak_ptr<type>> params;
};
}

View File

@ -161,35 +161,30 @@ namespace lily {
} }
} }
static type_ptr type_tree(program& prog, pgs_tree* type, const char* source) { static type* type_tree(program& prog, pgs_tree* type, const char* source) {
std::string str = tree_str(PGS_TREE_NT_CHILD(*type, 0), source); std::string str = tree_str(PGS_TREE_NT_CHILD(*type, 0), source);
if(!prog.types.count(str)) throw error("unknown type"); return prog.type_mgr.require_type(str);
return prog.types[str];
} }
static void collect_type_params(program& prog, std::vector<std::weak_ptr<type>>& into, pgs_tree* params, const char* source) { static void collect_type_params(program& prog, std::vector<type*>& into, pgs_tree* params, const char* source) {
while(true) { while(true) {
pgs_tree* param = PGS_TREE_NT_CHILD(*params, 0); pgs_tree* param = PGS_TREE_NT_CHILD(*params, 0);
into.push_back(std::weak_ptr<type>(type_tree(prog, param, source))); into.push_back(type_tree(prog, param, source));
if(PGS_TREE_NT_COUNT(*params) == 1) break; if(PGS_TREE_NT_COUNT(*params) == 1) break;
params = PGS_TREE_NT_CHILD(*params, 2); params = PGS_TREE_NT_CHILD(*params, 2);
} }
} }
static void collect_constructors(program& prog, int parent, pgs_tree* def, const char* source) { static void collect_constructors(program& prog, type_data* parent, pgs_tree* def, const char* source) {
int id = 0; int id = 0;
while(true) { while(true) {
constructor cons;
cons.tag = id++;
cons.parent_type = parent;
pgs_tree* elem = PGS_TREE_NT_CHILD(*def, 0); pgs_tree* elem = PGS_TREE_NT_CHILD(*def, 0);
std::vector<type*> params;
std::string name = tree_str(PGS_TREE_NT_CHILD(*elem, 0), source); std::string name = tree_str(PGS_TREE_NT_CHILD(*elem, 0), source);
if(PGS_TREE_NT_COUNT(*elem) > 1) if(PGS_TREE_NT_COUNT(*elem) > 1)
collect_type_params(prog, cons.params, PGS_TREE_NT_CHILD(*elem, 2), source); collect_type_params(prog, params, PGS_TREE_NT_CHILD(*elem, 2), source);
prog.constructors[name] = std::move(cons); parent->create_constructor(name, std::move(params));
if(PGS_TREE_NT_COUNT(*def) == 1) break; if(PGS_TREE_NT_COUNT(*def) == 1) break;
def = PGS_TREE_NT_CHILD(*def, 2); def = PGS_TREE_NT_CHILD(*def, 2);
@ -211,10 +206,7 @@ namespace lily {
prog.functions[function_name] = std::move(new_function); prog.functions[function_name] = std::move(new_function);
} else { } else {
std::string data_name = tree_str(PGS_TREE_NT_CHILD(*def, 1), source); std::string data_name = tree_str(PGS_TREE_NT_CHILD(*def, 1), source);
if(prog.types.count(data_name)) throw error("cannot redefine type"); type_data* new_type = prog.type_mgr.create_data_type(data_name);
int new_type = prog.next_free_type_id++;
prog.types[data_name] = type_ptr(new type_int(new_type));
collect_constructors(prog, new_type, collect_constructors(prog, new_type,
PGS_TREE_NT_CHILD(*PGS_TREE_NT_CHILD(*def, PGS_TREE_NT_COUNT(*def) - 1), 1), source); PGS_TREE_NT_CHILD(*PGS_TREE_NT_CHILD(*def, PGS_TREE_NT_COUNT(*def) - 1), 1), source);
} }
@ -235,31 +227,6 @@ namespace lily {
return prog; return prog;
} }
static void dump_program(program& prog) {
std::cout << "Constructors:" << std::endl;
for(auto& pair : prog.constructors) {
std::cout << " " << pair.first << std::endl;
}
std::cout << std::endl;
std::cout << "Types:" << std::endl;
for(auto& pair : prog.types) {
std::cout << " " << pair.first << std::endl;
}
std::cout << std::endl;
std::cout << "Functions:" << std::endl;
for(auto& pair : prog.functions) {
function& f = pair.second;
std::cout << " " << pair.first;
for(auto& param : f.params) {
std::cout << " " << param;
}
std::cout << std::endl;
}
std::cout << std::endl;
}
program_ptr parse(std::string s) { program_ptr parse(std::string s) {
pgs_state state; pgs_state state;
pgs_tree* into; pgs_tree* into;
@ -271,14 +238,7 @@ namespace lily {
} }
program_ptr prog = build_program(into, s.c_str()); program_ptr prog = build_program(into, s.c_str());
dump_program(*prog);
pgs_free_tree(into); pgs_free_tree(into);
return prog; return prog;
} }
program::program() {
types["Int"] = type_ptr(new type_int(type_id_int));
types["String"] = type_ptr(new type_int(type_id_str));
next_free_type_id = type_id_last;
}
} }

View File

@ -5,16 +5,12 @@
#include "ast.hpp" #include "ast.hpp"
#include "function.hpp" #include "function.hpp"
#include "type.hpp" #include "type.hpp"
#include "data.hpp" #include "type_manager.hpp"
namespace lily { namespace lily {
struct program { struct program {
int next_free_type_id; type_manager type_mgr;
std::map<std::string, type_ptr> types;
std::map<std::string, constructor> constructors;
std::map<std::string, function> functions; std::map<std::string, function> functions;
program();
}; };
typedef std::unique_ptr<program> program_ptr; typedef std::unique_ptr<program> program_ptr;

15
src/type.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "type.hpp"
namespace lily {
type_data::constructor* type_data::create_constructor(const std::string& name,
std::vector<type*>&& params) {
auto new_constructor = std::make_unique<constructor>();
new_constructor->id = constructors.size();
new_constructor->parent = this;
new_constructor->params = std::move(params);
constructor* raw_ptr = new_constructor.get();
constructors.push_back(std::move(new_constructor));
return raw_ptr;
}
}

View File

@ -13,20 +13,32 @@ namespace lily {
virtual ~type() = default; virtual ~type() = default;
}; };
typedef std::shared_ptr<type> type_ptr; struct type_internal : type {
struct type_int : type {
int type_id; int type_id;
type_int(int id) : type_id(id) {} type_internal(int id) : type_id(id) {}
};
struct type_data : type {
struct constructor {
type_data* parent;
int id;
std::vector<type*> params;
};
int type_id;
std::vector<std::unique_ptr<constructor>> constructors;
type_data(int id) : type_id(id) {}
constructor* create_constructor(const std::string& name, std::vector<type*>&& params);
}; };
struct type_func : type { struct type_func : type {
type_ptr left; type* left;
type_ptr right; type* right;
type_func(type_ptr l, type_ptr r) : type_func(type* l, type* r) :
left(std::move(l)), right(std::move(r)) {} left(l), right(r) {}
}; };
} }

41
src/type_manager.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "type_manager.hpp"
#include <memory>
#include "error.hpp"
namespace lily {
type_manager::type_manager() {
create_int_type();
create_str_type();
}
type_internal* type_manager::create_int_type() {
auto new_type = std::make_unique<type_internal>(next_id++);
type_internal* raw_ptr = new_type.get();
types.push_back(std::move(new_type));
type_names["Int"] = raw_ptr;
return raw_ptr;
}
type_internal* type_manager::create_str_type() {
auto new_type = std::make_unique<type_internal>(next_id++);
type_internal* raw_ptr = new_type.get();
types.push_back(std::move(new_type));
type_names["Str"] = raw_ptr;
return raw_ptr;
}
type_data* type_manager::create_data_type(const std::string& name) {
if(type_names.count(name)) throw error("redefinition of type");
auto new_type = std::make_unique<type_data>(next_id++);
type_data* raw_ptr = new_type.get();
types.push_back(std::move(new_type));
type_names[name] = raw_ptr;
return raw_ptr;
}
type* type_manager::require_type(const std::string& name) {
if(!type_names.count(name)) throw error("invalid type name");
return type_names[name];
}
}

22
src/type_manager.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <memory>
#include <map>
#include <vector>
#include "type.hpp"
namespace lily {
class type_manager {
private:
int next_id;
std::vector<std::unique_ptr<type>> types;
std::map<std::string, type*> type_names;
public:
type_manager();
type_internal* create_int_type();
type_internal* create_str_type();
type_data* create_data_type(const std::string& name);
type* require_type(const std::string& name);
};
}