Start working on types.
This commit is contained in:
parent
7bd6913ac5
commit
1be78c3548
12
src/data.hpp
Normal file
12
src/data.hpp
Normal 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;
|
||||||
|
};
|
||||||
|
}
|
|
@ -4,7 +4,11 @@
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
try {
|
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) {
|
} catch(lily::error& e) {
|
||||||
std::cout << e.message << std::endl;
|
std::cout << e.message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,9 +146,9 @@ namespace lily {
|
||||||
if(PGS_TREE_NT_COUNT(*def) == 5) {
|
if(PGS_TREE_NT_COUNT(*def) == 5) {
|
||||||
pgs_tree* params = PGS_TREE_NT_CHILD(*def, 2);
|
pgs_tree* params = PGS_TREE_NT_CHILD(*def, 2);
|
||||||
do {
|
do {
|
||||||
pgs_tree* param = PGS_TREE_NT_CHILD(*def, 0);
|
pgs_tree* param = PGS_TREE_NT_CHILD(*params, 0);
|
||||||
params =
|
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 from = PGS_TREE_T_FROM(*param);
|
||||||
size_t to = PGS_TREE_T_TO(*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) {
|
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))];
|
size_t str_from = PGS_TREE_T_FROM(*PGS_TREE_NT_CHILD(*def, 0));
|
||||||
if(kw == 'd') {
|
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;
|
function new_function;
|
||||||
collect_params(new_function.params, def, source);
|
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);
|
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 {
|
} 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 {
|
do {
|
||||||
pgs_tree* definition = PGS_TREE_NT_CHILD(*program, 0);
|
pgs_tree* definition = PGS_TREE_NT_CHILD(*program, 0);
|
||||||
program =
|
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);
|
add_definition(*prog, definition, source);
|
||||||
} while(program);
|
} while(program);
|
||||||
|
@ -188,6 +234,31 @@ 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;
|
||||||
|
@ -199,7 +270,14 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,17 @@
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
#include "ast.hpp"
|
#include "ast.hpp"
|
||||||
#include "function.hpp"
|
#include "function.hpp"
|
||||||
|
#include "type.hpp"
|
||||||
|
#include "data.hpp"
|
||||||
|
|
||||||
namespace lily {
|
namespace lily {
|
||||||
struct program {
|
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;
|
std::map<std::string, function> functions;
|
||||||
|
|
||||||
|
program();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unique_ptr<program> program_ptr;
|
typedef std::unique_ptr<program> program_ptr;
|
||||||
|
|
32
src/type.hpp
Normal file
32
src/type.hpp
Normal 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)) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user