Roll back optimization changes.
This commit is contained in:
parent
8a44109f93
commit
39bc6bb99e
253
13/ast.cpp
253
13/ast.cpp
|
@ -212,6 +212,10 @@ type_ptr ast_case::typecheck(type_mgr& mgr, type_env_ptr& env) {
|
||||||
|
|
||||||
input_type = mgr.resolve(case_type, var);
|
input_type = mgr.resolve(case_type, var);
|
||||||
type_app* app_type;
|
type_app* app_type;
|
||||||
|
if(!(app_type = dynamic_cast<type_app*>(input_type.get())) ||
|
||||||
|
!dynamic_cast<type_data*>(app_type->constructor.get())) {
|
||||||
|
throw type_error("attempting case analysis of non-data type");
|
||||||
|
}
|
||||||
|
|
||||||
return branch_type;
|
return branch_type;
|
||||||
}
|
}
|
||||||
|
@ -223,219 +227,60 @@ void ast_case::translate(global_scope& scope) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct case_mappings {
|
|
||||||
using tag_type = typename T::tag_type;
|
|
||||||
std::map<tag_type, std::vector<instruction_ptr>> defined_cases;
|
|
||||||
std::optional<std::vector<instruction_ptr>> default_case;
|
|
||||||
|
|
||||||
std::vector<instruction_ptr>& make_case_for(tag_type tag) {
|
|
||||||
if(default_case)
|
|
||||||
throw compiler_error("attempted pattern match after catch-all");
|
|
||||||
return defined_cases[tag];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<instruction_ptr>& make_default_case() {
|
|
||||||
if(default_case)
|
|
||||||
throw compiler_error("attempted repeated use of catch-all");
|
|
||||||
default_case.emplace(std::vector<instruction_ptr>());
|
|
||||||
return *default_case;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<instruction_ptr>& get_specific_case_for(tag_type tag) {
|
|
||||||
auto existing_case = defined_cases.find(tag);
|
|
||||||
assert(existing_case != defined_cases.end());
|
|
||||||
return existing_case->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<instruction_ptr>& get_default_case() {
|
|
||||||
assert(default_case);
|
|
||||||
return *default_case;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<instruction_ptr>& get_case_for(tag_type tag) {
|
|
||||||
if(case_defined_for(tag)) return get_specific_case_for(tag);
|
|
||||||
return get_default_case();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool case_defined_for(tag_type tag) {
|
|
||||||
return defined_cases.find(tag) != defined_cases.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool default_case_defined() { return default_case.has_value(); }
|
|
||||||
|
|
||||||
size_t defined_cases_count() { return defined_cases.size(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct case_strategy_bool {
|
|
||||||
using tag_type = bool;
|
|
||||||
using repr_type = bool;
|
|
||||||
|
|
||||||
case_strategy_bool(const type* type) {}
|
|
||||||
|
|
||||||
tag_type tag_from_repr(repr_type b) { return b; }
|
|
||||||
|
|
||||||
repr_type repr_from_pattern(const pattern_ptr& pt) {
|
|
||||||
pattern_constr* cpat;
|
|
||||||
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())) ||
|
|
||||||
(cpat->constr != "True" && cpat->constr != "False") ||
|
|
||||||
cpat->params.size() != 0)
|
|
||||||
throw compiler_error(
|
|
||||||
"pattern cannot be converted to a boolean",
|
|
||||||
pt->loc);
|
|
||||||
return cpat->constr == "True";
|
|
||||||
}
|
|
||||||
|
|
||||||
void compile_branch(
|
|
||||||
const branch_ptr& branch,
|
|
||||||
const env_ptr& env,
|
|
||||||
repr_type repr,
|
|
||||||
std::vector<instruction_ptr>& into) {
|
|
||||||
branch->expr->compile(env_ptr(new env_offset(1, env)), into);
|
|
||||||
into.push_back(instruction_ptr(new instruction_slide(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t case_count() {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void into_instructions(
|
|
||||||
case_mappings<case_strategy_bool>& ms,
|
|
||||||
std::vector<instruction_ptr>& into) {
|
|
||||||
if(ms.defined_cases_count() == 0) {
|
|
||||||
for(auto& instruction : ms.get_default_case())
|
|
||||||
into.push_back(std::move(instruction));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
instruction_ijump* ijump = new instruction_ijump();
|
|
||||||
instruction_ptr inst(ijump);
|
|
||||||
ijump->branches.push_back(std::move(ms.get_case_for(false)));
|
|
||||||
ijump->tag_mappings[0] = 0;
|
|
||||||
ijump->branches.push_back(std::move(ms.get_case_for(true)));
|
|
||||||
ijump->tag_mappings[1] = 1;
|
|
||||||
into.push_back(std::move(inst));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct case_strategy_data {
|
|
||||||
using tag_type = int;
|
|
||||||
using repr_type = std::pair<const type_data::constructor*, const std::vector<std::string>*>;
|
|
||||||
|
|
||||||
const type_data* arg_type;
|
|
||||||
|
|
||||||
case_strategy_data(const type* t) {
|
|
||||||
arg_type = dynamic_cast<const type_data*>(t);
|
|
||||||
assert(arg_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
tag_type tag_from_repr(const repr_type& repr) { return repr.first->tag; }
|
|
||||||
|
|
||||||
repr_type repr_from_pattern(const pattern_ptr& pt) {
|
|
||||||
pattern_constr* cpat;
|
|
||||||
if(!(cpat = dynamic_cast<pattern_constr*>(pt.get())))
|
|
||||||
throw compiler_error(
|
|
||||||
"pattern cannot be interpreted as constructor.",
|
|
||||||
pt->loc);
|
|
||||||
return std::make_pair(
|
|
||||||
&arg_type->constructors.find(cpat->constr)->second,
|
|
||||||
&cpat->params);
|
|
||||||
}
|
|
||||||
|
|
||||||
void compile_branch(
|
|
||||||
const branch_ptr& branch,
|
|
||||||
const env_ptr& env,
|
|
||||||
const repr_type& repr,
|
|
||||||
std::vector<instruction_ptr>& into) {
|
|
||||||
env_ptr new_env = env;
|
|
||||||
for(auto it = repr.second->rbegin(); it != repr.second->rend(); it++) {
|
|
||||||
new_env = env_ptr(new env_var(*it, new_env));
|
|
||||||
}
|
|
||||||
|
|
||||||
into.push_back(instruction_ptr(new instruction_split(repr.second->size())));
|
|
||||||
branch->expr->compile(new_env, into);
|
|
||||||
into.push_back(instruction_ptr(new instruction_slide(repr.second->size())));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t case_count() {
|
|
||||||
return arg_type->constructors.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void into_instructions(
|
|
||||||
case_mappings<case_strategy_data>& ms,
|
|
||||||
std::vector<instruction_ptr>& into) {
|
|
||||||
instruction_jump* jump_instruction = new instruction_jump();
|
|
||||||
instruction_ptr inst(jump_instruction);
|
|
||||||
|
|
||||||
for(auto& constr : arg_type->constructors) {
|
|
||||||
if(!ms.case_defined_for(constr.second.tag)) continue;
|
|
||||||
jump_instruction->branches.push_back(
|
|
||||||
std::move(ms.get_specific_case_for(constr.second.tag)));
|
|
||||||
jump_instruction->tag_mappings[constr.second.tag] =
|
|
||||||
jump_instruction->branches.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ms.default_case_defined()) {
|
|
||||||
jump_instruction->branches.push_back(
|
|
||||||
std::move(ms.get_default_case()));
|
|
||||||
for(auto& constr : arg_type->constructors) {
|
|
||||||
if(ms.case_defined_for(constr.second.tag)) continue;
|
|
||||||
jump_instruction->tag_mappings[constr.second.tag] =
|
|
||||||
jump_instruction->branches.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
into.push_back(std::move(inst));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void compile_case(const ast_case& node, const env_ptr& env, const type* type, std::vector<instruction_ptr>& into) {
|
|
||||||
T strategy(type);
|
|
||||||
case_mappings<T> cases;
|
|
||||||
for(auto& branch : node.branches) {
|
|
||||||
pattern_var* vpat;
|
|
||||||
if((vpat = dynamic_cast<pattern_var*>(branch->pat.get()))) {
|
|
||||||
if(cases.defined_cases_count() == strategy.case_count())
|
|
||||||
throw compiler_error("redundant catch-all pattern", branch->pat->loc);
|
|
||||||
auto& branch_into = cases.make_default_case();
|
|
||||||
env_ptr new_env(new env_var(vpat->var, env));
|
|
||||||
branch->expr->compile(new_env, branch_into);
|
|
||||||
branch_into.push_back(instruction_ptr(new instruction_slide(1)));
|
|
||||||
} else {
|
|
||||||
auto repr = strategy.repr_from_pattern(branch->pat);
|
|
||||||
auto& branch_into = cases.make_case_for(strategy.tag_from_repr(repr));
|
|
||||||
strategy.compile_branch(branch, env, repr, branch_into);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(cases.defined_cases_count() == strategy.case_count() ||
|
|
||||||
cases.default_case_defined()))
|
|
||||||
throw compiler_error("incomplete patterns", node.loc);
|
|
||||||
|
|
||||||
strategy.into_instructions(cases, into);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ast_case::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
|
void ast_case::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
|
||||||
type_app* app_type = dynamic_cast<type_app*>(input_type.get());
|
type_app* app_type = dynamic_cast<type_app*>(input_type.get());
|
||||||
type_data* data;
|
type_data* type = dynamic_cast<type_data*>(app_type->constructor.get());
|
||||||
type_base *base;
|
|
||||||
|
|
||||||
of->compile(env, into);
|
of->compile(env, into);
|
||||||
into.push_back(instruction_ptr(new instruction_eval()));
|
into.push_back(instruction_ptr(new instruction_eval()));
|
||||||
|
|
||||||
if(app_type && (data = dynamic_cast<type_data*>(app_type->constructor.get()))) {
|
instruction_jump* jump_instruction = new instruction_jump();
|
||||||
compile_case<case_strategy_data>(*this, env, data, into);
|
into.push_back(instruction_ptr(jump_instruction));
|
||||||
return;
|
for(auto& branch : branches) {
|
||||||
} else if (app_type && (base = dynamic_cast<type_base *>(app_type->constructor.get()))) {
|
std::vector<instruction_ptr> branch_instructions;
|
||||||
if (base->name == "Bool") {
|
pattern_var* vpat;
|
||||||
compile_case<case_strategy_bool>(*this, env, data, into);
|
pattern_constr* cpat;
|
||||||
return;
|
|
||||||
|
if((vpat = dynamic_cast<pattern_var*>(branch->pat.get()))) {
|
||||||
|
branch->expr->compile(env_ptr(new env_offset(1, env)), branch_instructions);
|
||||||
|
|
||||||
|
for(auto& constr_pair : type->constructors) {
|
||||||
|
if(jump_instruction->tag_mappings.find(constr_pair.second.tag) !=
|
||||||
|
jump_instruction->tag_mappings.end())
|
||||||
|
break;
|
||||||
|
|
||||||
|
jump_instruction->tag_mappings[constr_pair.second.tag] =
|
||||||
|
jump_instruction->branches.size();
|
||||||
|
}
|
||||||
|
jump_instruction->branches.push_back(std::move(branch_instructions));
|
||||||
|
} else if((cpat = dynamic_cast<pattern_constr*>(branch->pat.get()))) {
|
||||||
|
env_ptr new_env = env;
|
||||||
|
for(auto it = cpat->params.rbegin(); it != cpat->params.rend(); it++) {
|
||||||
|
new_env = env_ptr(new env_var(*it, new_env));
|
||||||
|
}
|
||||||
|
|
||||||
|
branch_instructions.push_back(instruction_ptr(new instruction_split(
|
||||||
|
cpat->params.size())));
|
||||||
|
branch->expr->compile(new_env, branch_instructions);
|
||||||
|
branch_instructions.push_back(instruction_ptr(new instruction_slide(
|
||||||
|
cpat->params.size())));
|
||||||
|
|
||||||
|
int new_tag = type->constructors[cpat->constr].tag;
|
||||||
|
if(jump_instruction->tag_mappings.find(new_tag) !=
|
||||||
|
jump_instruction->tag_mappings.end())
|
||||||
|
throw type_error("technically not a type error: duplicate pattern");
|
||||||
|
|
||||||
|
jump_instruction->tag_mappings[new_tag] =
|
||||||
|
jump_instruction->branches.size();
|
||||||
|
jump_instruction->branches.push_back(std::move(branch_instructions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw type_error("attempting unsupported case analysis", of->loc);
|
for(auto& constr_pair : type->constructors) {
|
||||||
|
if(jump_instruction->tag_mappings.find(constr_pair.second.tag) ==
|
||||||
|
jump_instruction->tag_mappings.end())
|
||||||
|
throw type_error("non-total pattern");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_let::print(int indent, std::ostream& to) const {
|
void ast_let::print(int indent, std::ostream& to) const {
|
||||||
|
|
|
@ -6,9 +6,6 @@ std::string op_name(binop op) {
|
||||||
case MINUS: return "-";
|
case MINUS: return "-";
|
||||||
case TIMES: return "*";
|
case TIMES: return "*";
|
||||||
case DIVIDE: return "/";
|
case DIVIDE: return "/";
|
||||||
case MODULO: return "%";
|
|
||||||
case EQUALS: return "==";
|
|
||||||
case LESS_EQUALS: return "<=";
|
|
||||||
}
|
}
|
||||||
return "??";
|
return "??";
|
||||||
}
|
}
|
||||||
|
@ -19,9 +16,6 @@ std::string op_action(binop op) {
|
||||||
case MINUS: return "minus";
|
case MINUS: return "minus";
|
||||||
case TIMES: return "times";
|
case TIMES: return "times";
|
||||||
case DIVIDE: return "divide";
|
case DIVIDE: return "divide";
|
||||||
case MODULO: return "modulo";
|
|
||||||
case EQUALS: return "equals";
|
|
||||||
case LESS_EQUALS: return "less_equals";
|
|
||||||
}
|
}
|
||||||
return "??";
|
return "??";
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,11 @@ enum binop {
|
||||||
PLUS,
|
PLUS,
|
||||||
MINUS,
|
MINUS,
|
||||||
TIMES,
|
TIMES,
|
||||||
DIVIDE,
|
DIVIDE
|
||||||
MODULO,
|
|
||||||
EQUALS,
|
|
||||||
LESS_EQUALS,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr binop all_binops[] = {
|
constexpr binop all_binops[] = {
|
||||||
PLUS, MINUS, TIMES, DIVIDE, MODULO,
|
PLUS, MINUS, TIMES, DIVIDE
|
||||||
EQUALS, LESS_EQUALS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string op_name(binop op);
|
std::string op_name(binop op);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
void compiler::add_default_types() {
|
void compiler::add_default_types() {
|
||||||
global_env->bind_type("Int", type_ptr(new type_base("Int")));
|
global_env->bind_type("Int", type_ptr(new type_base("Int")));
|
||||||
global_env->bind_type("Bool", type_ptr(new type_base("Bool")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::add_binop_type(binop op, type_ptr type) {
|
void compiler::add_binop_type(binop op, type_ptr type) {
|
||||||
|
@ -31,24 +30,11 @@ void compiler::add_default_function_types() {
|
||||||
assert(int_type != nullptr);
|
assert(int_type != nullptr);
|
||||||
type_ptr int_type_app = type_ptr(new type_app(int_type));
|
type_ptr int_type_app = type_ptr(new type_app(int_type));
|
||||||
|
|
||||||
type_ptr bool_type = global_env->lookup_type("Bool");
|
|
||||||
assert(bool_type != nullptr);
|
|
||||||
type_ptr bool_type_app = type_ptr(new type_app(bool_type));
|
|
||||||
|
|
||||||
type_ptr closed_int_op_type(
|
type_ptr closed_int_op_type(
|
||||||
new type_arr(int_type_app, type_ptr(new type_arr(int_type_app, int_type_app))));
|
new type_arr(int_type_app, type_ptr(new type_arr(int_type_app, int_type_app))));
|
||||||
type_ptr compare_int_op_type(
|
|
||||||
new type_arr(int_type_app, type_ptr(new type_arr(int_type_app, bool_type_app))));
|
|
||||||
|
|
||||||
constexpr binop closed_ops[] = { PLUS, MINUS, TIMES, DIVIDE, MODULO };
|
constexpr binop closed_ops[] = { PLUS, MINUS, TIMES, DIVIDE };
|
||||||
constexpr binop compare_ops[] = { EQUALS, LESS_EQUALS };
|
|
||||||
for(auto& op : closed_ops) add_binop_type(op, closed_int_op_type);
|
for(auto& op : closed_ops) add_binop_type(op, closed_int_op_type);
|
||||||
for(auto& op : compare_ops) add_binop_type(op, compare_int_op_type);
|
|
||||||
|
|
||||||
for(auto name : { "True", "False" }) {
|
|
||||||
global_env->bind(name, bool_type_app, visibility::global);
|
|
||||||
global_env->set_mangled_name(name, mng.new_mangled_name(name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::parse() {
|
void compiler::parse() {
|
||||||
|
@ -94,25 +80,10 @@ void compiler::create_llvm_binop(binop op) {
|
||||||
ctx.get_builder().CreateRetVoid();
|
ctx.get_builder().CreateRetVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler::create_llvm_bool(bool b) {
|
|
||||||
auto new_function = ctx.create_custom_function(
|
|
||||||
global_env->get_mangled_name(b ? "True" : "False"), 0);
|
|
||||||
std::vector<instruction_ptr> instructions;
|
|
||||||
instructions.push_back(instruction_ptr(new instruction_pushint(b)));
|
|
||||||
instructions.push_back(instruction_ptr(new instruction_update(0)));
|
|
||||||
ctx.get_builder().SetInsertPoint(&new_function->getEntryBlock());
|
|
||||||
for(auto& instruction : instructions) {
|
|
||||||
instruction->gen_llvm(ctx, new_function);
|
|
||||||
}
|
|
||||||
ctx.get_builder().CreateRetVoid();
|
|
||||||
}
|
|
||||||
|
|
||||||
void compiler::generate_llvm() {
|
void compiler::generate_llvm() {
|
||||||
for(auto op : all_binops) {
|
for(auto op : all_binops) {
|
||||||
create_llvm_binop(op);
|
create_llvm_binop(op);
|
||||||
}
|
}
|
||||||
create_llvm_bool(true);
|
|
||||||
create_llvm_bool(false);
|
|
||||||
|
|
||||||
global_scp.generate_llvm(ctx);
|
global_scp.generate_llvm(ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ class compiler {
|
||||||
void translate();
|
void translate();
|
||||||
void compile();
|
void compile();
|
||||||
void create_llvm_binop(binop op);
|
void create_llvm_binop(binop op);
|
||||||
void create_llvm_bool(bool b);
|
|
||||||
void generate_llvm();
|
void generate_llvm();
|
||||||
void output_llvm(const std::string& into);
|
void output_llvm(const std::string& into);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -100,7 +100,7 @@ void instruction_jump::print(int indent, std::ostream& to) const {
|
||||||
|
|
||||||
void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const {
|
void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const {
|
||||||
auto top_node = ctx.create_peek(f, ctx.create_size(0));
|
auto top_node = ctx.create_peek(f, ctx.create_size(0));
|
||||||
auto tag = get_case_value(ctx, top_node);
|
auto tag = ctx.unwrap_data_tag(top_node);
|
||||||
auto safety_block = ctx.create_basic_block("safety", f);
|
auto safety_block = ctx.create_basic_block("safety", f);
|
||||||
auto switch_op = ctx.get_builder().CreateSwitch(tag, safety_block, tag_mappings.size());
|
auto switch_op = ctx.get_builder().CreateSwitch(tag, safety_block, tag_mappings.size());
|
||||||
std::vector<BasicBlock*> blocks;
|
std::vector<BasicBlock*> blocks;
|
||||||
|
@ -122,14 +122,6 @@ void instruction_jump::gen_llvm(llvm_context& ctx, Function* f) const {
|
||||||
ctx.get_builder().SetInsertPoint(safety_block);
|
ctx.get_builder().SetInsertPoint(safety_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* instruction_jump::get_case_value(llvm_context& ctx, Value* v) const {
|
|
||||||
return ctx.unwrap_data_tag(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* instruction_ijump::get_case_value(llvm_context& ctx, Value* v) const {
|
|
||||||
return ctx.unwrap_num(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void instruction_slide::print(int indent, std::ostream& to) const {
|
void instruction_slide::print(int indent, std::ostream& to) const {
|
||||||
print_indent(indent, to);
|
print_indent(indent, to);
|
||||||
to << "Slide(" << offset << ")" << std::endl;
|
to << "Slide(" << offset << ")" << std::endl;
|
||||||
|
@ -153,9 +145,6 @@ void instruction_binop::gen_llvm(llvm_context& ctx, Function* f) const {
|
||||||
case MINUS: result = ctx.get_builder().CreateSub(left_int, right_int); break;
|
case MINUS: result = ctx.get_builder().CreateSub(left_int, right_int); break;
|
||||||
case TIMES: result = ctx.get_builder().CreateMul(left_int, right_int); break;
|
case TIMES: result = ctx.get_builder().CreateMul(left_int, right_int); break;
|
||||||
case DIVIDE: result = ctx.get_builder().CreateSDiv(left_int, right_int); break;
|
case DIVIDE: result = ctx.get_builder().CreateSDiv(left_int, right_int); break;
|
||||||
case MODULO: result = ctx.get_builder().CreateSRem(left_int, right_int); break;
|
|
||||||
case EQUALS: result = ctx.get_builder().CreateICmpEQ(left_int, right_int); break;
|
|
||||||
case LESS_EQUALS: result = ctx.get_builder().CreateICmpSLE(left_int, right_int); break;
|
|
||||||
}
|
}
|
||||||
ctx.create_push(f, ctx.create_num(f, result));
|
ctx.create_push(f, ctx.create_num(f, result));
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,12 +99,6 @@ struct instruction_jump : public instruction {
|
||||||
|
|
||||||
void print(int indent, std::ostream& to) const;
|
void print(int indent, std::ostream& to) const;
|
||||||
void gen_llvm(llvm_context& ctx, llvm::Function* f) const;
|
void gen_llvm(llvm_context& ctx, llvm::Function* f) const;
|
||||||
|
|
||||||
virtual llvm::Value* get_case_value(llvm_context& ctx, llvm::Value*) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct instruction_ijump : public instruction_jump {
|
|
||||||
llvm::Value* get_case_value(llvm_context& ctx, llvm::Value*) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct instruction_slide : public instruction {
|
struct instruction_slide : public instruction {
|
||||||
|
|
|
@ -237,7 +237,12 @@ Value* llvm_context::unwrap_gmachine_stack_ptr(Value* g) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* llvm_context::unwrap_num(Value* v) {
|
Value* llvm_context::unwrap_num(Value* v) {
|
||||||
return builder.CreatePtrToInt(v, IntegerType::getInt32Ty(ctx));
|
auto num_ptr_type = PointerType::getUnqual(struct_types.at("node_num"));
|
||||||
|
auto cast = builder.CreatePointerCast(v, num_ptr_type);
|
||||||
|
auto offset_0 = create_i32(0);
|
||||||
|
auto offset_1 = create_i32(1);
|
||||||
|
auto int_ptr = builder.CreateGEP(cast, { offset_0, offset_1 });
|
||||||
|
return builder.CreateLoad(int_ptr);
|
||||||
}
|
}
|
||||||
Value* llvm_context::create_num(Function* f, Value* v) {
|
Value* llvm_context::create_num(Function* f, Value* v) {
|
||||||
auto alloc_num_f = functions.at("alloc_num");
|
auto alloc_num_f = functions.at("alloc_num");
|
||||||
|
|
47
13/parser.y
47
13/parser.y
|
@ -18,14 +18,10 @@ using yyscan_t = void*;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token BACKSLASH
|
%token BACKSLASH
|
||||||
%token BACKTICK
|
|
||||||
%token PLUS
|
%token PLUS
|
||||||
%token TIMES
|
%token TIMES
|
||||||
%token MINUS
|
%token MINUS
|
||||||
%token DIVIDE
|
%token DIVIDE
|
||||||
%token MODULO
|
|
||||||
%token EQUALS
|
|
||||||
%token LESS_EQUALS
|
|
||||||
%token <int> INT
|
%token <int> INT
|
||||||
%token DEFN
|
%token DEFN
|
||||||
%token DATA
|
%token DATA
|
||||||
|
@ -53,10 +49,9 @@ using yyscan_t = void*;
|
||||||
%type <std::vector<branch_ptr>> branches
|
%type <std::vector<branch_ptr>> branches
|
||||||
%type <std::vector<constructor_ptr>> constructors
|
%type <std::vector<constructor_ptr>> constructors
|
||||||
%type <std::vector<parsed_type_ptr>> typeList
|
%type <std::vector<parsed_type_ptr>> typeList
|
||||||
%type <binop> anyBinop
|
|
||||||
%type <definition_group> definitions
|
%type <definition_group> definitions
|
||||||
%type <parsed_type_ptr> type nonArrowType typeListElement
|
%type <parsed_type_ptr> type nonArrowType typeListElement
|
||||||
%type <ast_ptr> aInfix aEq aAdd aMul case let lambda app appBase
|
%type <ast_ptr> aAdd aMul case let lambda app appBase
|
||||||
%type <definition_data_ptr> data
|
%type <definition_data_ptr> data
|
||||||
%type <definition_defn_ptr> defn
|
%type <definition_defn_ptr> defn
|
||||||
%type <branch_ptr> branch
|
%type <branch_ptr> branch
|
||||||
|
@ -78,7 +73,7 @@ definitions
|
||||||
;
|
;
|
||||||
|
|
||||||
defn
|
defn
|
||||||
: DEFN LID lowercaseParams EQUAL OCURLY aInfix CCURLY
|
: DEFN LID lowercaseParams EQUAL OCURLY aAdd CCURLY
|
||||||
{ $$ = definition_defn_ptr(
|
{ $$ = definition_defn_ptr(
|
||||||
new definition_defn(std::move($2), std::move($3), std::move($6), @$)); }
|
new definition_defn(std::move($2), std::move($3), std::move($6), @$)); }
|
||||||
;
|
;
|
||||||
|
@ -88,22 +83,6 @@ lowercaseParams
|
||||||
| lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); }
|
| lowercaseParams LID { $$ = std::move($1); $$.push_back(std::move($2)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
aInfix
|
|
||||||
: aInfix BACKTICK LID BACKTICK aEq
|
|
||||||
{ $$ = ast_ptr(new ast_app(
|
|
||||||
ast_ptr(new ast_app(ast_ptr(new ast_lid(std::move($3))), std::move($1))), std::move($5))); }
|
|
||||||
| aInfix BACKTICK UID BACKTICK aEq
|
|
||||||
{ $$ = ast_ptr(new ast_app(
|
|
||||||
ast_ptr(new ast_app(ast_ptr(new ast_uid(std::move($3))), std::move($1))), std::move($5))); }
|
|
||||||
| aEq { $$ = std::move($1); }
|
|
||||||
;
|
|
||||||
|
|
||||||
aEq
|
|
||||||
: aAdd EQUALS aAdd { $$ = ast_ptr(new ast_binop(EQUALS, std::move($1), std::move($3), @$)); }
|
|
||||||
| aAdd LESS_EQUALS aAdd { $$ = ast_ptr(new ast_binop(LESS_EQUALS, std::move($1), std::move($3), @$)); }
|
|
||||||
| aAdd { $$ = std::move($1); }
|
|
||||||
;
|
|
||||||
|
|
||||||
aAdd
|
aAdd
|
||||||
: aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3), @$)); }
|
: aAdd PLUS aMul { $$ = ast_ptr(new ast_binop(PLUS, std::move($1), std::move($3), @$)); }
|
||||||
| aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3), @$)); }
|
| aAdd MINUS aMul { $$ = ast_ptr(new ast_binop(MINUS, std::move($1), std::move($3), @$)); }
|
||||||
|
@ -113,7 +92,6 @@ aAdd
|
||||||
aMul
|
aMul
|
||||||
: aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3), @$)); }
|
: aMul TIMES app { $$ = ast_ptr(new ast_binop(TIMES, std::move($1), std::move($3), @$)); }
|
||||||
| aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3), @$)); }
|
| aMul DIVIDE app { $$ = ast_ptr(new ast_binop(DIVIDE, std::move($1), std::move($3), @$)); }
|
||||||
| aMul MODULO app { $$ = ast_ptr(new ast_binop(MODULO, std::move($1), std::move($3), @$)); }
|
|
||||||
| app { $$ = std::move($1); }
|
| app { $$ = std::move($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -126,35 +104,24 @@ appBase
|
||||||
: INT { $$ = ast_ptr(new ast_int($1, @$)); }
|
: INT { $$ = ast_ptr(new ast_int($1, @$)); }
|
||||||
| LID { $$ = ast_ptr(new ast_lid(std::move($1), @$)); }
|
| LID { $$ = ast_ptr(new ast_lid(std::move($1), @$)); }
|
||||||
| UID { $$ = ast_ptr(new ast_uid(std::move($1), @$)); }
|
| UID { $$ = ast_ptr(new ast_uid(std::move($1), @$)); }
|
||||||
| OPAREN aInfix CPAREN { $$ = std::move($2); }
|
| OPAREN aAdd CPAREN { $$ = std::move($2); }
|
||||||
| OPAREN anyBinop CPAREN { $$ = ast_ptr(new ast_lid(op_name($2))); }
|
|
||||||
| case { $$ = std::move($1); }
|
| case { $$ = std::move($1); }
|
||||||
| let { $$ = std::move($1); }
|
| let { $$ = std::move($1); }
|
||||||
| lambda { $$ = std::move($1); }
|
| lambda { $$ = std::move($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
anyBinop
|
|
||||||
: PLUS { $$ = PLUS; }
|
|
||||||
| MINUS { $$ = MINUS; }
|
|
||||||
| TIMES { $$ = TIMES; }
|
|
||||||
| DIVIDE { $$ = DIVIDE; }
|
|
||||||
| MODULO { $$ = MODULO; }
|
|
||||||
| EQUALS { $$ = EQUALS; }
|
|
||||||
| LESS_EQUALS { $$ = LESS_EQUALS; }
|
|
||||||
;
|
|
||||||
|
|
||||||
let
|
let
|
||||||
: LET OCURLY definitions CCURLY IN OCURLY aInfix CCURLY
|
: LET OCURLY definitions CCURLY IN OCURLY aAdd CCURLY
|
||||||
{ $$ = ast_ptr(new ast_let(std::move($3), std::move($7), @$)); }
|
{ $$ = ast_ptr(new ast_let(std::move($3), std::move($7), @$)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
lambda
|
lambda
|
||||||
: BACKSLASH lowercaseParams ARROW OCURLY aInfix CCURLY
|
: BACKSLASH lowercaseParams ARROW OCURLY aAdd CCURLY
|
||||||
{ $$ = ast_ptr(new ast_lambda(std::move($2), std::move($5), @$)); }
|
{ $$ = ast_ptr(new ast_lambda(std::move($2), std::move($5), @$)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
case
|
case
|
||||||
: CASE aInfix OF OCURLY branches CCURLY
|
: CASE aAdd OF OCURLY branches CCURLY
|
||||||
{ $$ = ast_ptr(new ast_case(std::move($2), std::move($5), @$)); }
|
{ $$ = ast_ptr(new ast_case(std::move($2), std::move($5), @$)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -164,7 +131,7 @@ branches
|
||||||
;
|
;
|
||||||
|
|
||||||
branch
|
branch
|
||||||
: pattern ARROW OCURLY aInfix CCURLY
|
: pattern ARROW OCURLY aAdd CCURLY
|
||||||
{ $$ = branch_ptr(new branch(std::move($1), std::move($4))); }
|
{ $$ = branch_ptr(new branch(std::move($1), std::move($4))); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
23
13/runtime.c
23
13/runtime.c
|
@ -1,13 +1,9 @@
|
||||||
#include <bits/stdint-intn.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
#define TOGGLE_MARK(n) ((uint64_t) n ^ ((uint64_t) 1 << 63))
|
|
||||||
#define IS_MARKED(n) ((((uint64_t) n) ^ ((uint64_t) n << 1)) & ((uint64_t) 1 << 63))
|
|
||||||
|
|
||||||
struct node_base* alloc_node() {
|
struct node_base* alloc_node() {
|
||||||
struct node_base* new_node = malloc(sizeof(struct node_app));
|
struct node_base* new_node = malloc(sizeof(struct node_app));
|
||||||
new_node->gc_next = NULL;
|
new_node->gc_next = NULL;
|
||||||
|
@ -25,7 +21,10 @@ struct node_app* alloc_app(struct node_base* l, struct node_base* r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_num* alloc_num(int32_t n) {
|
struct node_num* alloc_num(int32_t n) {
|
||||||
return (struct node_num*) TOGGLE_MARK(n);
|
struct node_num* node = (struct node_num*) alloc_node();
|
||||||
|
node->base.tag = NODE_NUM;
|
||||||
|
node->value = n;
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) {
|
struct node_global* alloc_global(void (*f)(struct gmachine*), int32_t a) {
|
||||||
|
@ -50,7 +49,7 @@ void free_node_direct(struct node_base* n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc_visit_node(struct node_base* n) {
|
void gc_visit_node(struct node_base* n) {
|
||||||
if(IS_MARKED(n) || n->gc_reachable) return;
|
if(n->gc_reachable) return;
|
||||||
n->gc_reachable = 1;
|
n->gc_reachable = 1;
|
||||||
|
|
||||||
if(n->tag == NODE_APP) {
|
if(n->tag == NODE_APP) {
|
||||||
|
@ -170,7 +169,6 @@ void gmachine_split(struct gmachine* g, size_t n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) {
|
struct node_base* gmachine_track(struct gmachine* g, struct node_base* b) {
|
||||||
if(IS_MARKED(b)) return b;
|
|
||||||
g->gc_node_count++;
|
g->gc_node_count++;
|
||||||
b->gc_next = g->gc_nodes;
|
b->gc_next = g->gc_nodes;
|
||||||
g->gc_nodes = b;
|
g->gc_nodes = b;
|
||||||
|
@ -210,9 +208,7 @@ void unwind(struct gmachine* g) {
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
struct node_base* peek = stack_peek(s, 0);
|
struct node_base* peek = stack_peek(s, 0);
|
||||||
if(IS_MARKED(peek)) {
|
if(peek->tag == NODE_APP) {
|
||||||
break;
|
|
||||||
} else if(peek->tag == NODE_APP) {
|
|
||||||
struct node_app* n = (struct node_app*) peek;
|
struct node_app* n = (struct node_app*) peek;
|
||||||
stack_push(s, n->left);
|
stack_push(s, n->left);
|
||||||
} else if(peek->tag == NODE_GLOBAL) {
|
} else if(peek->tag == NODE_GLOBAL) {
|
||||||
|
@ -238,9 +234,7 @@ void unwind(struct gmachine* g) {
|
||||||
extern void f_main(struct gmachine* s);
|
extern void f_main(struct gmachine* s);
|
||||||
|
|
||||||
void print_node(struct node_base* n) {
|
void print_node(struct node_base* n) {
|
||||||
if(IS_MARKED(n)) {
|
if(n->tag == NODE_APP) {
|
||||||
printf("%d", (int32_t) n);
|
|
||||||
} else if(n->tag == NODE_APP) {
|
|
||||||
struct node_app* app = (struct node_app*) n;
|
struct node_app* app = (struct node_app*) n;
|
||||||
print_node(app->left);
|
print_node(app->left);
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
|
@ -252,6 +246,9 @@ void print_node(struct node_base* n) {
|
||||||
printf("(Global: %p)", global->function);
|
printf("(Global: %p)", global->function);
|
||||||
} else if(n->tag == NODE_IND) {
|
} else if(n->tag == NODE_IND) {
|
||||||
print_node(((struct node_ind*) n)->next);
|
print_node(((struct node_ind*) n)->next);
|
||||||
|
} else if(n->tag == NODE_NUM) {
|
||||||
|
struct node_num* num = (struct node_num*) n;
|
||||||
|
printf("%d", num->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
492
13/scanner.hpp
492
13/scanner.hpp
|
@ -1,492 +0,0 @@
|
||||||
#ifndef yyHEADER_H
|
|
||||||
#define yyHEADER_H 1
|
|
||||||
#define yyIN_HEADER 1
|
|
||||||
|
|
||||||
#line 5 "scanner.hpp"
|
|
||||||
|
|
||||||
#line 7 "scanner.hpp"
|
|
||||||
|
|
||||||
#define YY_INT_ALIGNED short int
|
|
||||||
|
|
||||||
/* A lexical scanner generated by flex */
|
|
||||||
|
|
||||||
#define FLEX_SCANNER
|
|
||||||
#define YY_FLEX_MAJOR_VERSION 2
|
|
||||||
#define YY_FLEX_MINOR_VERSION 6
|
|
||||||
#define YY_FLEX_SUBMINOR_VERSION 4
|
|
||||||
#if YY_FLEX_SUBMINOR_VERSION > 0
|
|
||||||
#define FLEX_BETA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* First, we deal with platform-specific or compiler-specific issues. */
|
|
||||||
|
|
||||||
/* begin standard C headers. */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* end standard C headers. */
|
|
||||||
|
|
||||||
/* flex integer type definitions */
|
|
||||||
|
|
||||||
#ifndef FLEXINT_H
|
|
||||||
#define FLEXINT_H
|
|
||||||
|
|
||||||
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
|
|
||||||
|
|
||||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
|
||||||
|
|
||||||
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
|
|
||||||
* if you want the limit (max/min) macros for int types.
|
|
||||||
*/
|
|
||||||
#ifndef __STDC_LIMIT_MACROS
|
|
||||||
#define __STDC_LIMIT_MACROS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
typedef int8_t flex_int8_t;
|
|
||||||
typedef uint8_t flex_uint8_t;
|
|
||||||
typedef int16_t flex_int16_t;
|
|
||||||
typedef uint16_t flex_uint16_t;
|
|
||||||
typedef int32_t flex_int32_t;
|
|
||||||
typedef uint32_t flex_uint32_t;
|
|
||||||
#else
|
|
||||||
typedef signed char flex_int8_t;
|
|
||||||
typedef short int flex_int16_t;
|
|
||||||
typedef int flex_int32_t;
|
|
||||||
typedef unsigned char flex_uint8_t;
|
|
||||||
typedef unsigned short int flex_uint16_t;
|
|
||||||
typedef unsigned int flex_uint32_t;
|
|
||||||
|
|
||||||
/* Limits of integral types. */
|
|
||||||
#ifndef INT8_MIN
|
|
||||||
#define INT8_MIN (-128)
|
|
||||||
#endif
|
|
||||||
#ifndef INT16_MIN
|
|
||||||
#define INT16_MIN (-32767-1)
|
|
||||||
#endif
|
|
||||||
#ifndef INT32_MIN
|
|
||||||
#define INT32_MIN (-2147483647-1)
|
|
||||||
#endif
|
|
||||||
#ifndef INT8_MAX
|
|
||||||
#define INT8_MAX (127)
|
|
||||||
#endif
|
|
||||||
#ifndef INT16_MAX
|
|
||||||
#define INT16_MAX (32767)
|
|
||||||
#endif
|
|
||||||
#ifndef INT32_MAX
|
|
||||||
#define INT32_MAX (2147483647)
|
|
||||||
#endif
|
|
||||||
#ifndef UINT8_MAX
|
|
||||||
#define UINT8_MAX (255U)
|
|
||||||
#endif
|
|
||||||
#ifndef UINT16_MAX
|
|
||||||
#define UINT16_MAX (65535U)
|
|
||||||
#endif
|
|
||||||
#ifndef UINT32_MAX
|
|
||||||
#define UINT32_MAX (4294967295U)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SIZE_MAX
|
|
||||||
#define SIZE_MAX (~(size_t)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ! C99 */
|
|
||||||
|
|
||||||
#endif /* ! FLEXINT_H */
|
|
||||||
|
|
||||||
/* begin standard C++ headers. */
|
|
||||||
|
|
||||||
/* TODO: this is always defined, so inline it */
|
|
||||||
#define yyconst const
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
|
||||||
#define yynoreturn __attribute__((__noreturn__))
|
|
||||||
#else
|
|
||||||
#define yynoreturn
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* An opaque pointer. */
|
|
||||||
#ifndef YY_TYPEDEF_YY_SCANNER_T
|
|
||||||
#define YY_TYPEDEF_YY_SCANNER_T
|
|
||||||
typedef void* yyscan_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* For convenience, these vars (plus the bison vars far below)
|
|
||||||
are macros in the reentrant scanner. */
|
|
||||||
#define yyin yyg->yyin_r
|
|
||||||
#define yyout yyg->yyout_r
|
|
||||||
#define yyextra yyg->yyextra_r
|
|
||||||
#define yyleng yyg->yyleng_r
|
|
||||||
#define yytext yyg->yytext_r
|
|
||||||
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
|
|
||||||
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
|
|
||||||
#define yy_flex_debug yyg->yy_flex_debug_r
|
|
||||||
|
|
||||||
/* Size of default input buffer. */
|
|
||||||
#ifndef YY_BUF_SIZE
|
|
||||||
#ifdef __ia64__
|
|
||||||
/* On IA-64, the buffer size is 16k, not 8k.
|
|
||||||
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
|
|
||||||
* Ditto for the __ia64__ case accordingly.
|
|
||||||
*/
|
|
||||||
#define YY_BUF_SIZE 32768
|
|
||||||
#else
|
|
||||||
#define YY_BUF_SIZE 16384
|
|
||||||
#endif /* __ia64__ */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
|
|
||||||
#define YY_TYPEDEF_YY_BUFFER_STATE
|
|
||||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef YY_TYPEDEF_YY_SIZE_T
|
|
||||||
#define YY_TYPEDEF_YY_SIZE_T
|
|
||||||
typedef size_t yy_size_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef YY_STRUCT_YY_BUFFER_STATE
|
|
||||||
#define YY_STRUCT_YY_BUFFER_STATE
|
|
||||||
struct yy_buffer_state
|
|
||||||
{
|
|
||||||
FILE *yy_input_file;
|
|
||||||
|
|
||||||
char *yy_ch_buf; /* input buffer */
|
|
||||||
char *yy_buf_pos; /* current position in input buffer */
|
|
||||||
|
|
||||||
/* Size of input buffer in bytes, not including room for EOB
|
|
||||||
* characters.
|
|
||||||
*/
|
|
||||||
int yy_buf_size;
|
|
||||||
|
|
||||||
/* Number of characters read into yy_ch_buf, not including EOB
|
|
||||||
* characters.
|
|
||||||
*/
|
|
||||||
int yy_n_chars;
|
|
||||||
|
|
||||||
/* Whether we "own" the buffer - i.e., we know we created it,
|
|
||||||
* and can realloc() it to grow it, and should free() it to
|
|
||||||
* delete it.
|
|
||||||
*/
|
|
||||||
int yy_is_our_buffer;
|
|
||||||
|
|
||||||
/* Whether this is an "interactive" input source; if so, and
|
|
||||||
* if we're using stdio for input, then we want to use getc()
|
|
||||||
* instead of fread(), to make sure we stop fetching input after
|
|
||||||
* each newline.
|
|
||||||
*/
|
|
||||||
int yy_is_interactive;
|
|
||||||
|
|
||||||
/* Whether we're considered to be at the beginning of a line.
|
|
||||||
* If so, '^' rules will be active on the next match, otherwise
|
|
||||||
* not.
|
|
||||||
*/
|
|
||||||
int yy_at_bol;
|
|
||||||
|
|
||||||
int yy_bs_lineno; /**< The line count. */
|
|
||||||
int yy_bs_column; /**< The column count. */
|
|
||||||
|
|
||||||
/* Whether to try to fill the input buffer when we reach the
|
|
||||||
* end of it.
|
|
||||||
*/
|
|
||||||
int yy_fill_buffer;
|
|
||||||
|
|
||||||
int yy_buffer_status;
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
|
|
||||||
|
|
||||||
void yyrestart ( FILE *input_file , yyscan_t yyscanner );
|
|
||||||
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
|
|
||||||
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
|
|
||||||
void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
|
|
||||||
void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
|
|
||||||
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
|
|
||||||
void yypop_buffer_state ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
|
|
||||||
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
|
|
||||||
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
|
|
||||||
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
|
|
||||||
void yyfree ( void * , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
/* Begin user sect3 */
|
|
||||||
|
|
||||||
#define yywrap(yyscanner) (/*CONSTCOND*/1)
|
|
||||||
#define YY_SKIP_YYWRAP
|
|
||||||
|
|
||||||
#define yytext_ptr yytext_r
|
|
||||||
|
|
||||||
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
|
|
||||||
#define INITIAL 0
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef YY_NO_UNISTD_H
|
|
||||||
/* Special case for "unistd.h", since it is non-ANSI. We include it way
|
|
||||||
* down here because we want the user's section 1 to have been scanned first.
|
|
||||||
* The user has a chance to override it with an option.
|
|
||||||
*/
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef YY_EXTRA_TYPE
|
|
||||||
#define YY_EXTRA_TYPE void *
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int yylex_init (yyscan_t* scanner);
|
|
||||||
|
|
||||||
int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
|
|
||||||
|
|
||||||
/* Accessor methods to globals.
|
|
||||||
These are made visible to non-reentrant scanners for convenience. */
|
|
||||||
|
|
||||||
int yylex_destroy ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
int yyget_debug ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
void yyset_debug ( int debug_flag , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
FILE *yyget_in ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
FILE *yyget_out ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
int yyget_leng ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
char *yyget_text ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
int yyget_lineno ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
void yyset_lineno ( int _line_number , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
int yyget_column ( yyscan_t yyscanner );
|
|
||||||
|
|
||||||
void yyset_column ( int _column_no , yyscan_t yyscanner );
|
|
||||||
|
|
||||||
/* Macros after this point can all be overridden by user definitions in
|
|
||||||
* section 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef YY_SKIP_YYWRAP
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" int yywrap ( yyscan_t yyscanner );
|
|
||||||
#else
|
|
||||||
extern int yywrap ( yyscan_t yyscanner );
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef yytext_ptr
|
|
||||||
static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef YY_NEED_STRLEN
|
|
||||||
static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef YY_NO_INPUT
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Amount of stuff to slurp up with each read. */
|
|
||||||
#ifndef YY_READ_BUF_SIZE
|
|
||||||
#ifdef __ia64__
|
|
||||||
/* On IA-64, the buffer size is 16k, not 8k */
|
|
||||||
#define YY_READ_BUF_SIZE 16384
|
|
||||||
#else
|
|
||||||
#define YY_READ_BUF_SIZE 8192
|
|
||||||
#endif /* __ia64__ */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Number of entries by which start-condition stack grows. */
|
|
||||||
#ifndef YY_START_STACK_INCR
|
|
||||||
#define YY_START_STACK_INCR 25
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Default declaration of generated scanner - a define so the user can
|
|
||||||
* easily add parameters.
|
|
||||||
*/
|
|
||||||
#ifndef YY_DECL
|
|
||||||
#define YY_DECL_IS_OURS 1
|
|
||||||
|
|
||||||
extern int yylex (yyscan_t yyscanner);
|
|
||||||
|
|
||||||
#define YY_DECL int yylex (yyscan_t yyscanner)
|
|
||||||
#endif /* !YY_DECL */
|
|
||||||
|
|
||||||
/* yy_get_previous_state - get the state just before the EOB char was reached */
|
|
||||||
|
|
||||||
#undef YY_NEW_FILE
|
|
||||||
#undef YY_FLUSH_BUFFER
|
|
||||||
#undef yy_set_bol
|
|
||||||
#undef yy_new_buffer
|
|
||||||
#undef yy_set_interactive
|
|
||||||
#undef YY_DO_BEFORE_ACTION
|
|
||||||
|
|
||||||
#ifdef YY_DECL_IS_OURS
|
|
||||||
#undef YY_DECL_IS_OURS
|
|
||||||
#undef YY_DECL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef yy_create_buffer_ALREADY_DEFINED
|
|
||||||
#undef yy_create_buffer
|
|
||||||
#endif
|
|
||||||
#ifndef yy_delete_buffer_ALREADY_DEFINED
|
|
||||||
#undef yy_delete_buffer
|
|
||||||
#endif
|
|
||||||
#ifndef yy_scan_buffer_ALREADY_DEFINED
|
|
||||||
#undef yy_scan_buffer
|
|
||||||
#endif
|
|
||||||
#ifndef yy_scan_string_ALREADY_DEFINED
|
|
||||||
#undef yy_scan_string
|
|
||||||
#endif
|
|
||||||
#ifndef yy_scan_bytes_ALREADY_DEFINED
|
|
||||||
#undef yy_scan_bytes
|
|
||||||
#endif
|
|
||||||
#ifndef yy_init_buffer_ALREADY_DEFINED
|
|
||||||
#undef yy_init_buffer
|
|
||||||
#endif
|
|
||||||
#ifndef yy_flush_buffer_ALREADY_DEFINED
|
|
||||||
#undef yy_flush_buffer
|
|
||||||
#endif
|
|
||||||
#ifndef yy_load_buffer_state_ALREADY_DEFINED
|
|
||||||
#undef yy_load_buffer_state
|
|
||||||
#endif
|
|
||||||
#ifndef yy_switch_to_buffer_ALREADY_DEFINED
|
|
||||||
#undef yy_switch_to_buffer
|
|
||||||
#endif
|
|
||||||
#ifndef yypush_buffer_state_ALREADY_DEFINED
|
|
||||||
#undef yypush_buffer_state
|
|
||||||
#endif
|
|
||||||
#ifndef yypop_buffer_state_ALREADY_DEFINED
|
|
||||||
#undef yypop_buffer_state
|
|
||||||
#endif
|
|
||||||
#ifndef yyensure_buffer_stack_ALREADY_DEFINED
|
|
||||||
#undef yyensure_buffer_stack
|
|
||||||
#endif
|
|
||||||
#ifndef yylex_ALREADY_DEFINED
|
|
||||||
#undef yylex
|
|
||||||
#endif
|
|
||||||
#ifndef yyrestart_ALREADY_DEFINED
|
|
||||||
#undef yyrestart
|
|
||||||
#endif
|
|
||||||
#ifndef yylex_init_ALREADY_DEFINED
|
|
||||||
#undef yylex_init
|
|
||||||
#endif
|
|
||||||
#ifndef yylex_init_extra_ALREADY_DEFINED
|
|
||||||
#undef yylex_init_extra
|
|
||||||
#endif
|
|
||||||
#ifndef yylex_destroy_ALREADY_DEFINED
|
|
||||||
#undef yylex_destroy
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_debug_ALREADY_DEFINED
|
|
||||||
#undef yyget_debug
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_debug_ALREADY_DEFINED
|
|
||||||
#undef yyset_debug
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_extra_ALREADY_DEFINED
|
|
||||||
#undef yyget_extra
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_extra_ALREADY_DEFINED
|
|
||||||
#undef yyset_extra
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_in_ALREADY_DEFINED
|
|
||||||
#undef yyget_in
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_in_ALREADY_DEFINED
|
|
||||||
#undef yyset_in
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_out_ALREADY_DEFINED
|
|
||||||
#undef yyget_out
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_out_ALREADY_DEFINED
|
|
||||||
#undef yyset_out
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_leng_ALREADY_DEFINED
|
|
||||||
#undef yyget_leng
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_text_ALREADY_DEFINED
|
|
||||||
#undef yyget_text
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_lineno_ALREADY_DEFINED
|
|
||||||
#undef yyget_lineno
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_lineno_ALREADY_DEFINED
|
|
||||||
#undef yyset_lineno
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_column_ALREADY_DEFINED
|
|
||||||
#undef yyget_column
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_column_ALREADY_DEFINED
|
|
||||||
#undef yyset_column
|
|
||||||
#endif
|
|
||||||
#ifndef yywrap_ALREADY_DEFINED
|
|
||||||
#undef yywrap
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_lval_ALREADY_DEFINED
|
|
||||||
#undef yyget_lval
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_lval_ALREADY_DEFINED
|
|
||||||
#undef yyset_lval
|
|
||||||
#endif
|
|
||||||
#ifndef yyget_lloc_ALREADY_DEFINED
|
|
||||||
#undef yyget_lloc
|
|
||||||
#endif
|
|
||||||
#ifndef yyset_lloc_ALREADY_DEFINED
|
|
||||||
#undef yyset_lloc
|
|
||||||
#endif
|
|
||||||
#ifndef yyalloc_ALREADY_DEFINED
|
|
||||||
#undef yyalloc
|
|
||||||
#endif
|
|
||||||
#ifndef yyrealloc_ALREADY_DEFINED
|
|
||||||
#undef yyrealloc
|
|
||||||
#endif
|
|
||||||
#ifndef yyfree_ALREADY_DEFINED
|
|
||||||
#undef yyfree
|
|
||||||
#endif
|
|
||||||
#ifndef yytext_ALREADY_DEFINED
|
|
||||||
#undef yytext
|
|
||||||
#endif
|
|
||||||
#ifndef yyleng_ALREADY_DEFINED
|
|
||||||
#undef yyleng
|
|
||||||
#endif
|
|
||||||
#ifndef yyin_ALREADY_DEFINED
|
|
||||||
#undef yyin
|
|
||||||
#endif
|
|
||||||
#ifndef yyout_ALREADY_DEFINED
|
|
||||||
#undef yyout
|
|
||||||
#endif
|
|
||||||
#ifndef yy_flex_debug_ALREADY_DEFINED
|
|
||||||
#undef yy_flex_debug
|
|
||||||
#endif
|
|
||||||
#ifndef yylineno_ALREADY_DEFINED
|
|
||||||
#undef yylineno
|
|
||||||
#endif
|
|
||||||
#ifndef yytables_fload_ALREADY_DEFINED
|
|
||||||
#undef yytables_fload
|
|
||||||
#endif
|
|
||||||
#ifndef yytables_destroy_ALREADY_DEFINED
|
|
||||||
#undef yytables_destroy
|
|
||||||
#endif
|
|
||||||
#ifndef yyTABLES_NAME_ALREADY_DEFINED
|
|
||||||
#undef yyTABLES_NAME
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#line 49 "/home/vanilla/projects/blog-static/code/compiler/13/scanner.l"
|
|
||||||
|
|
||||||
|
|
||||||
#line 490 "scanner.hpp"
|
|
||||||
#undef yyIN_HEADER
|
|
||||||
#endif /* yyHEADER_H */
|
|
|
@ -24,10 +24,6 @@
|
||||||
\* { return yy::parser::make_TIMES(LOC); }
|
\* { return yy::parser::make_TIMES(LOC); }
|
||||||
- { return yy::parser::make_MINUS(LOC); }
|
- { return yy::parser::make_MINUS(LOC); }
|
||||||
\/ { return yy::parser::make_DIVIDE(LOC); }
|
\/ { return yy::parser::make_DIVIDE(LOC); }
|
||||||
% { return yy::parser::make_MODULO(LOC); }
|
|
||||||
== { return yy::parser::make_EQUALS(LOC); }
|
|
||||||
\<= { return yy::parser::make_LESS_EQUALS(LOC); }
|
|
||||||
` { return yy::parser::make_BACKTICK(LOC); }
|
|
||||||
[0-9]+ { return yy::parser::make_INT(atoi(yytext), LOC); }
|
[0-9]+ { return yy::parser::make_INT(atoi(yytext), LOC); }
|
||||||
defn { return yy::parser::make_DEFN(LOC); }
|
defn { return yy::parser::make_DEFN(LOC); }
|
||||||
data { return yy::parser::make_DATA(LOC); }
|
data { return yy::parser::make_DATA(LOC); }
|
||||||
|
|
|
@ -38,10 +38,6 @@ void type_base::print(const type_mgr& mgr, std::ostream& to) const {
|
||||||
to << name;
|
to << name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_internal::print(const type_mgr& mgr, std::ostream& to) const {
|
|
||||||
to << "!" << name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void type_arr::print(const type_mgr& mgr, std::ostream& to) const {
|
void type_arr::print(const type_mgr& mgr, std::ostream& to) const {
|
||||||
type_var* var;
|
type_var* var;
|
||||||
bool print_parenths = dynamic_cast<type_arr*>(mgr.resolve(left, var).get()) != nullptr;
|
bool print_parenths = dynamic_cast<type_arr*>(mgr.resolve(left, var).get()) != nullptr;
|
||||||
|
@ -128,8 +124,7 @@ void type_mgr::unify(type_ptr l, type_ptr r, const std::optional<yy::location>&
|
||||||
} else if((lid = dynamic_cast<type_base*>(l.get())) &&
|
} else if((lid = dynamic_cast<type_base*>(l.get())) &&
|
||||||
(rid = dynamic_cast<type_base*>(r.get()))) {
|
(rid = dynamic_cast<type_base*>(r.get()))) {
|
||||||
if(lid->name == rid->name &&
|
if(lid->name == rid->name &&
|
||||||
lid->arity == rid->arity &&
|
lid->arity == rid->arity)
|
||||||
lid->is_internal() == rid->is_internal())
|
|
||||||
return;
|
return;
|
||||||
} else if((lapp = dynamic_cast<type_app*>(l.get())) &&
|
} else if((lapp = dynamic_cast<type_app*>(l.get())) &&
|
||||||
(rapp = dynamic_cast<type_app*>(r.get()))) {
|
(rapp = dynamic_cast<type_app*>(r.get()))) {
|
||||||
|
|
11
13/type.hpp
11
13/type.hpp
|
@ -46,17 +46,6 @@ struct type_base : public type {
|
||||||
: name(std::move(n)), arity(a) {}
|
: name(std::move(n)), arity(a) {}
|
||||||
|
|
||||||
void print(const type_mgr& mgr, std::ostream& to) const;
|
void print(const type_mgr& mgr, std::ostream& to) const;
|
||||||
|
|
||||||
virtual bool is_internal() const { return false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct type_internal : public type_base {
|
|
||||||
type_internal(std::string n, int32_t a = 0)
|
|
||||||
: type_base(std::move(n), a) {}
|
|
||||||
|
|
||||||
void print(const type_mgr& mgr, std::ostream& to) const;
|
|
||||||
|
|
||||||
bool is_internal() const { return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct type_data : public type_base {
|
struct type_data : public type_base {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user