diff --git a/CMakeLists.txt b/CMakeLists.txt index fe44a89..a5576f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) +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) diff --git a/src/data.hpp b/src/data.hpp deleted file mode 100644 index dc049b5..0000000 --- a/src/data.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include -#include "type.hpp" - -namespace lily { - struct constructor { - int parent_type; - int tag; - std::vector> params; - }; -} diff --git a/src/parser.cpp b/src/parser.cpp index 97bbfe9..c34d4e6 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -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); - if(!prog.types.count(str)) throw error("unknown type"); - - return prog.types[str]; + return prog.type_mgr.require_type(str); } - static void collect_type_params(program& prog, std::vector>& into, pgs_tree* params, const char* source) { + static void collect_type_params(program& prog, std::vector& into, pgs_tree* params, const char* source) { while(true) { pgs_tree* param = PGS_TREE_NT_CHILD(*params, 0); - into.push_back(std::weak_ptr(type_tree(prog, param, source))); + into.push_back(type_tree(prog, param, source)); if(PGS_TREE_NT_COUNT(*params) == 1) break; 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; while(true) { - constructor cons; - cons.tag = id++; - cons.parent_type = parent; - pgs_tree* elem = PGS_TREE_NT_CHILD(*def, 0); + std::vector params; std::string name = tree_str(PGS_TREE_NT_CHILD(*elem, 0), source); if(PGS_TREE_NT_COUNT(*elem) > 1) - collect_type_params(prog, cons.params, PGS_TREE_NT_CHILD(*elem, 2), source); - prog.constructors[name] = std::move(cons); + collect_type_params(prog, params, PGS_TREE_NT_CHILD(*elem, 2), source); + parent->create_constructor(name, std::move(params)); if(PGS_TREE_NT_COUNT(*def) == 1) break; def = PGS_TREE_NT_CHILD(*def, 2); @@ -211,10 +206,7 @@ namespace lily { prog.functions[function_name] = std::move(new_function); } else { std::string data_name = tree_str(PGS_TREE_NT_CHILD(*def, 1), source); - if(prog.types.count(data_name)) throw error("cannot redefine type"); - - int new_type = prog.next_free_type_id++; - prog.types[data_name] = type_ptr(new type_int(new_type)); + type_data* new_type = prog.type_mgr.create_data_type(data_name); collect_constructors(prog, new_type, 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; } - 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) { pgs_state state; pgs_tree* into; @@ -271,14 +238,7 @@ namespace lily { } program_ptr prog = build_program(into, s.c_str()); - dump_program(*prog); pgs_free_tree(into); 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; - } } diff --git a/src/parser.hpp b/src/parser.hpp index f979840..efbc2ea 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -5,16 +5,12 @@ #include "ast.hpp" #include "function.hpp" #include "type.hpp" -#include "data.hpp" +#include "type_manager.hpp" namespace lily { struct program { - int next_free_type_id; - std::map types; - std::map constructors; + type_manager type_mgr; std::map functions; - - program(); }; typedef std::unique_ptr program_ptr; diff --git a/src/type.cpp b/src/type.cpp new file mode 100644 index 0000000..0925c25 --- /dev/null +++ b/src/type.cpp @@ -0,0 +1,15 @@ +#include "type.hpp" + +namespace lily { + type_data::constructor* type_data::create_constructor(const std::string& name, + std::vector&& params) { + auto new_constructor = std::make_unique(); + 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; + } +} diff --git a/src/type.hpp b/src/type.hpp index f71ea5c..acef15a 100644 --- a/src/type.hpp +++ b/src/type.hpp @@ -13,20 +13,32 @@ namespace lily { virtual ~type() = default; }; - typedef std::shared_ptr type_ptr; - - struct type_int : type { + struct type_internal : type { 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 params; + }; + + int type_id; + std::vector> constructors; + + type_data(int id) : type_id(id) {} + constructor* create_constructor(const std::string& name, std::vector&& params); }; struct type_func : type { - type_ptr left; - type_ptr right; + type* left; + type* right; - type_func(type_ptr l, type_ptr r) : - left(std::move(l)), right(std::move(r)) {} + type_func(type* l, type* r) : + left(l), right(r) {} }; } diff --git a/src/type_manager.cpp b/src/type_manager.cpp new file mode 100644 index 0000000..e495f8e --- /dev/null +++ b/src/type_manager.cpp @@ -0,0 +1,41 @@ +#include "type_manager.hpp" +#include +#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(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(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(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]; + } +} diff --git a/src/type_manager.hpp b/src/type_manager.hpp new file mode 100644 index 0000000..5b45984 --- /dev/null +++ b/src/type_manager.hpp @@ -0,0 +1,22 @@ +#pragma once +#include +#include +#include +#include "type.hpp" + +namespace lily { + class type_manager { + private: + int next_id; + std::vector> types; + std::map 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); + }; +}