Start working on types.

This commit is contained in:
Danila Fedorin 2019-06-05 21:16:40 -07:00
parent 7bd6913ac5
commit 1be78c3548
5 changed files with 142 additions and 9 deletions

12
src/data.hpp Normal file
View File

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

View File

@ -4,7 +4,11 @@
int main() {
try {
lily::parse("defn add x y = { x + y }");
lily::parse(
"data Bool = { True, False }\n"
"data Color = { Red, Black }\n"
"data IntList = { Nil, Cons(Int, Int) }\n"
"defn add x y = { x + y }");
} catch(lily::error& e) {
std::cout << e.message << std::endl;
}

View File

@ -146,9 +146,9 @@ namespace lily {
if(PGS_TREE_NT_COUNT(*def) == 5) {
pgs_tree* params = PGS_TREE_NT_CHILD(*def, 2);
do {
pgs_tree* param = PGS_TREE_NT_CHILD(*def, 0);
pgs_tree* param = PGS_TREE_NT_CHILD(*params, 0);
params =
(PGS_TREE_NT_COUNT(*def) == 2) ? PGS_TREE_NT_CHILD(*def, 1) : nullptr;
(PGS_TREE_NT_COUNT(*params) == 2) ? PGS_TREE_NT_CHILD(*params, 1) : nullptr;
size_t from = PGS_TREE_T_FROM(*param);
size_t to = PGS_TREE_T_TO(*param);
@ -160,16 +160,62 @@ namespace lily {
}
}
static type_ptr 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];
}
static void collect_type_params(program& prog, std::vector<type_ptr>& into, pgs_tree* params, const char* source) {
while(true) {
pgs_tree* param = PGS_TREE_NT_CHILD(*params, 0);
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) {
int id = 0;
while(true) {
constructor cons;
cons.tag = id++;
cons.parent_type = parent;
pgs_tree* elem = PGS_TREE_NT_CHILD(*def, 0);
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);
if(PGS_TREE_NT_COUNT(*def) == 1) break;
def = PGS_TREE_NT_CHILD(*def, 2);
}
}
static void add_definition(program& prog, pgs_tree* def, const char* source) {
char kw = source[PGS_TREE_T_FROM(*PGS_TREE_NT_CHILD(*def, 0))];
if(kw == 'd') {
size_t str_from = PGS_TREE_T_FROM(*PGS_TREE_NT_CHILD(*def, 0));
if(source[str_from]== 't') {
// skip for now
} else if(source[str_from + 1] == 'e') {
std::string function_name = tree_str(PGS_TREE_NT_CHILD(*def, 1), source);
if(prog.functions.count(function_name)) throw error("cannot redefine function");
function new_function;
collect_params(new_function.params, def, source);
new_function.body = expr_tree(PGS_TREE_NT_CHILD(*PGS_TREE_NT_CHILD(*def, PGS_TREE_NT_COUNT(*def) - 1), 1), source);
} else if(kw == 't') {
// skip for now
prog.functions[function_name] = std::move(new_function);
} else {
// skip for now
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++;
collect_constructors(prog, new_type,
PGS_TREE_NT_CHILD(*PGS_TREE_NT_CHILD(*def, PGS_TREE_NT_COUNT(*def) - 1), 1), source);
prog.types[data_name] = type_ptr(new type_int(new_type));
}
}
@ -180,7 +226,7 @@ namespace lily {
do {
pgs_tree* definition = PGS_TREE_NT_CHILD(*program, 0);
program =
(PGS_TREE_NT_COUNT(*tree) == 2) ? PGS_TREE_NT_CHILD(*tree, 1) : nullptr;
(PGS_TREE_NT_COUNT(*program) == 2) ? PGS_TREE_NT_CHILD(*program, 1) : nullptr;
add_definition(*prog, definition, source);
} while(program);
@ -188,6 +234,31 @@ 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;
@ -199,7 +270,14 @@ 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;
}
}

View File

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

32
src/type.hpp Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <string>
#include <vector>
namespace lily {
enum reserved_types {
type_id_int = 0,
type_id_str,
type_id_last
};
struct type {
virtual ~type() = default;
};
typedef std::shared_ptr<type> type_ptr;
struct type_int : type {
int type_id;
type_int(int id) : type_id(id) {}
};
struct type_func : type {
type_ptr left;
type_ptr right;
type_func(type_ptr l, type_ptr r) :
left(std::move(l)), right(std::move(r)) {}
};
}