Rewrite types to not use IDs unless needed.
This commit is contained in:
parent
f3be325644
commit
1e77622589
|
@ -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)
|
||||||
|
|
12
src/data.hpp
12
src/data.hpp
|
@ -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;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
15
src/type.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
28
src/type.hpp
28
src/type.hpp
|
@ -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
41
src/type_manager.cpp
Normal 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
22
src/type_manager.hpp
Normal 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);
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user