Make some refactors for name mangling and encapsulation.
This commit is contained in:
parent
18aac4c8fd
commit
ed1f9a1460
|
@ -38,6 +38,8 @@ add_executable(compiler
|
|||
graph.cpp graph.hpp
|
||||
global_scope.cpp global_scope.hpp
|
||||
parse_driver.cpp parse_driver.hpp
|
||||
mangler.cpp mangler.hpp
|
||||
compiler.cpp compiler.hpp
|
||||
${BISON_parser_OUTPUTS}
|
||||
${FLEX_scanner_OUTPUTS}
|
||||
main.cpp
|
||||
|
|
|
@ -57,9 +57,8 @@ void ast_lid::translate(global_scope& scope) {
|
|||
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
|
||||
into.push_back(instruction_ptr(
|
||||
(this->env->is_global(id)) ?
|
||||
(instruction*) new instruction_pushglobal(id) :
|
||||
(instruction*) new instruction_push(
|
||||
env->get_offset(this->env->get_mangled_name(id)))));
|
||||
(instruction*) new instruction_pushglobal(this->env->get_mangled_name(id)) :
|
||||
(instruction*) new instruction_push(env->get_offset(id))));
|
||||
}
|
||||
|
||||
void ast_uid::print(int indent, std::ostream& to) const {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
enum binop {
|
||||
|
@ -11,5 +12,10 @@ enum binop {
|
|||
LESS_EQUALS,
|
||||
};
|
||||
|
||||
constexpr binop all_binops[] = {
|
||||
PLUS, MINUS, TIMES, DIVIDE, MODULO,
|
||||
EQUALS, LESS_EQUALS
|
||||
};
|
||||
|
||||
std::string op_name(binop op);
|
||||
std::string op_action(binop op);
|
||||
|
|
181
13/compiler.cpp
Normal file
181
13/compiler.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
#include "compiler.hpp"
|
||||
#include "binop.hpp"
|
||||
#include "error.hpp"
|
||||
#include "global_scope.hpp"
|
||||
#include "parse_driver.hpp"
|
||||
#include "type.hpp"
|
||||
#include "type_env.hpp"
|
||||
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
void compiler::add_default_types() {
|
||||
global_env->bind_type("Int", type_ptr(new type_internal("Int")));
|
||||
global_env->bind_type("Bool", type_ptr(new type_internal("Bool")));
|
||||
}
|
||||
|
||||
void compiler::add_binop_type(binop op, type_ptr type) {
|
||||
auto name = mng.new_mangled_name(op_action(op));
|
||||
binop_names[op] = name;
|
||||
global_env->bind(op_name(op), std::move(type), visibility::global);
|
||||
global_env->set_mangled_name(op_name(op), name);
|
||||
}
|
||||
|
||||
void compiler::add_default_function_types() {
|
||||
type_ptr int_type = global_env->lookup_type("Int");
|
||||
assert(int_type != nullptr);
|
||||
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(
|
||||
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 compare_ops[] = { EQUALS, LESS_EQUALS };
|
||||
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() {
|
||||
if(!driver.run_parse())
|
||||
throw compiler_error("failed to open file");
|
||||
}
|
||||
|
||||
void compiler::typecheck() {
|
||||
std::set<std::string> free_variables;
|
||||
global_defs.find_free(free_variables);
|
||||
global_defs.typecheck(type_m, global_env);
|
||||
}
|
||||
|
||||
void compiler::translate() {
|
||||
for(auto& data : global_defs.defs_data) {
|
||||
data.second->into_globals(global_scp);
|
||||
}
|
||||
for(auto& defn : global_defs.defs_defn) {
|
||||
auto& function = defn.second->into_global(global_scp);
|
||||
function.body->env->parent->set_mangled_name(defn.first, function.name);
|
||||
}
|
||||
}
|
||||
|
||||
void compiler::compile() {
|
||||
global_scp.compile();
|
||||
}
|
||||
|
||||
void compiler::create_llvm_binop(binop op) {
|
||||
auto new_function = ctx.create_custom_function(binop_names.at(op), 2);
|
||||
std::vector<instruction_ptr> instructions;
|
||||
instructions.push_back(instruction_ptr(new instruction_push(1)));
|
||||
instructions.push_back(instruction_ptr(new instruction_eval()));
|
||||
instructions.push_back(instruction_ptr(new instruction_push(1)));
|
||||
instructions.push_back(instruction_ptr(new instruction_eval()));
|
||||
instructions.push_back(instruction_ptr(new instruction_binop(op)));
|
||||
instructions.push_back(instruction_ptr(new instruction_update(2)));
|
||||
instructions.push_back(instruction_ptr(new instruction_pop(2)));
|
||||
ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
|
||||
for(auto& instruction : instructions) {
|
||||
instruction->gen_llvm(ctx, new_function);
|
||||
}
|
||||
ctx.builder.CreateRetVoid();
|
||||
}
|
||||
|
||||
void compiler::create_llvm_bool(bool b) {
|
||||
auto new_function = ctx.create_custom_function(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.builder.SetInsertPoint(&new_function->getEntryBlock());
|
||||
for(auto& instruction : instructions) {
|
||||
instruction->gen_llvm(ctx, new_function);
|
||||
}
|
||||
ctx.builder.CreateRetVoid();
|
||||
}
|
||||
|
||||
void compiler::generate_llvm() {
|
||||
for(auto op : all_binops) {
|
||||
create_llvm_binop(op);
|
||||
}
|
||||
create_llvm_bool(true);
|
||||
create_llvm_bool(false);
|
||||
|
||||
global_scp.generate_llvm(ctx);
|
||||
}
|
||||
|
||||
void compiler::output_llvm(const std::string& into) {
|
||||
std::string targetTriple = llvm::sys::getDefaultTargetTriple();
|
||||
|
||||
llvm::InitializeNativeTarget();
|
||||
llvm::InitializeNativeTargetAsmParser();
|
||||
llvm::InitializeNativeTargetAsmPrinter();
|
||||
|
||||
std::string error;
|
||||
const llvm::Target* target =
|
||||
llvm::TargetRegistry::lookupTarget(targetTriple, error);
|
||||
if (!target) {
|
||||
std::cerr << error << std::endl;
|
||||
} else {
|
||||
std::string cpu = "generic";
|
||||
std::string features = "";
|
||||
llvm::TargetOptions options;
|
||||
std::unique_ptr<llvm::TargetMachine> targetMachine(
|
||||
target->createTargetMachine(targetTriple, cpu, features,
|
||||
options, llvm::Optional<llvm::Reloc::Model>()));
|
||||
|
||||
ctx.module.setDataLayout(targetMachine->createDataLayout());
|
||||
ctx.module.setTargetTriple(targetTriple);
|
||||
|
||||
std::error_code ec;
|
||||
llvm::raw_fd_ostream file(into, ec, llvm::sys::fs::F_None);
|
||||
if (ec) {
|
||||
throw compiler_error("failed to open object file for writing");
|
||||
} else {
|
||||
llvm::CodeGenFileType type = llvm::CGFT_ObjectFile;
|
||||
llvm::legacy::PassManager pm;
|
||||
if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) {
|
||||
throw compiler_error("failed to add passes to pass manager");
|
||||
} else {
|
||||
pm.run(ctx.module);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compiler::compiler(const std::string& filename)
|
||||
: file_m(), global_defs(), driver(file_m, global_defs, filename),
|
||||
mng(), global_scp(mng), global_env(new type_env), type_m(), ctx() {
|
||||
add_default_types();
|
||||
add_default_function_types();
|
||||
}
|
||||
|
||||
void compiler::operator()(const std::string& into) {
|
||||
parse();
|
||||
typecheck();
|
||||
translate();
|
||||
compile();
|
||||
generate_llvm();
|
||||
output_llvm(into);
|
||||
}
|
||||
|
||||
file_mgr& compiler::get_file_manager() {
|
||||
return file_m;
|
||||
}
|
||||
|
||||
type_mgr& compiler::get_type_manager() {
|
||||
return type_m;
|
||||
}
|
39
13/compiler.hpp
Normal file
39
13/compiler.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
#include "binop.hpp"
|
||||
#include "parse_driver.hpp"
|
||||
#include "definition.hpp"
|
||||
#include "type_env.hpp"
|
||||
#include "type.hpp"
|
||||
#include "global_scope.hpp"
|
||||
#include "mangler.hpp"
|
||||
#include "llvm_context.hpp"
|
||||
|
||||
class compiler {
|
||||
private:
|
||||
std::map<binop, std::string> binop_names;
|
||||
file_mgr file_m;
|
||||
definition_group global_defs;
|
||||
parse_driver driver;
|
||||
mangler mng;
|
||||
global_scope global_scp;
|
||||
type_env_ptr global_env;
|
||||
type_mgr type_m;
|
||||
llvm_context ctx;
|
||||
|
||||
void add_default_types();
|
||||
void add_binop_type(binop op, type_ptr type);
|
||||
void add_default_function_types();
|
||||
void parse();
|
||||
void typecheck();
|
||||
void translate();
|
||||
void compile();
|
||||
void create_llvm_binop(binop op);
|
||||
void create_llvm_bool(bool b);
|
||||
void generate_llvm();
|
||||
void output_llvm(const std::string& into);
|
||||
public:
|
||||
compiler(const std::string& filename);
|
||||
void operator()(const std::string& into);
|
||||
file_mgr& get_file_manager();
|
||||
type_mgr& get_type_manager();
|
||||
};
|
16
13/error.cpp
16
13/error.cpp
|
@ -9,28 +9,28 @@ void compiler_error::print_about(std::ostream& to) {
|
|||
to << description << std::endl;
|
||||
}
|
||||
|
||||
void compiler_error::print_location(std::ostream& to, parse_driver& drv, bool highlight) {
|
||||
void compiler_error::print_location(std::ostream& to, file_mgr& fm, bool highlight) {
|
||||
if(!loc) return;
|
||||
to << "occuring on line " << loc->begin.line << ":" << std::endl;
|
||||
drv.print_location(to, *loc, highlight);
|
||||
fm.print_location(to, *loc, highlight);
|
||||
}
|
||||
|
||||
void compiler_error::pretty_print(std::ostream& to, parse_driver& drv) {
|
||||
void compiler_error::pretty_print(std::ostream& to, file_mgr& fm) {
|
||||
print_about(to);
|
||||
print_location(to, drv);
|
||||
print_location(to, fm);
|
||||
}
|
||||
|
||||
const char* type_error::what() const noexcept {
|
||||
return "an error occured while checking the types of the program";
|
||||
}
|
||||
|
||||
void type_error::pretty_print(std::ostream& to, parse_driver& drv) {
|
||||
void type_error::pretty_print(std::ostream& to, file_mgr& fm) {
|
||||
print_about(to);
|
||||
print_location(to, drv, true);
|
||||
print_location(to, fm, true);
|
||||
}
|
||||
|
||||
void unification_error::pretty_print(std::ostream& to, parse_driver& drv, type_mgr& mgr) {
|
||||
type_error::pretty_print(to, drv);
|
||||
void unification_error::pretty_print(std::ostream& to, file_mgr& fm, type_mgr& mgr) {
|
||||
type_error::pretty_print(to, fm);
|
||||
to << "the expected type was:" << std::endl;
|
||||
to << " \033[34m";
|
||||
left->print(mgr, to);
|
||||
|
|
|
@ -17,9 +17,9 @@ struct compiler_error : std::exception {
|
|||
const char* what() const noexcept override;
|
||||
|
||||
void print_about(std::ostream& to);
|
||||
void print_location(std::ostream& to, parse_driver& drv, bool highlight = false);
|
||||
void print_location(std::ostream& to, file_mgr& fm, bool highlight = false);
|
||||
|
||||
void pretty_print(std::ostream& to, parse_driver& drv);
|
||||
void pretty_print(std::ostream& to, file_mgr& fm);
|
||||
};
|
||||
|
||||
struct type_error : compiler_error {
|
||||
|
@ -29,7 +29,7 @@ struct type_error : compiler_error {
|
|||
: compiler_error(std::move(d), std::move(l)) {}
|
||||
|
||||
const char* what() const noexcept override;
|
||||
void pretty_print(std::ostream& to, parse_driver& drv);
|
||||
void pretty_print(std::ostream& to, file_mgr& fm);
|
||||
};
|
||||
|
||||
struct unification_error : public type_error {
|
||||
|
@ -40,5 +40,5 @@ struct unification_error : public type_error {
|
|||
: left(std::move(l)), right(std::move(r)),
|
||||
type_error("failed to unify types", std::move(loc)) {}
|
||||
|
||||
void pretty_print(std::ostream& to, parse_driver& drv, type_mgr& mgr);
|
||||
void pretty_print(std::ostream& to, file_mgr& fm, type_mgr& mgr);
|
||||
};
|
||||
|
|
|
@ -36,14 +36,23 @@ void global_constructor::generate_llvm(llvm_context& ctx) {
|
|||
ctx.builder.CreateRetVoid();
|
||||
}
|
||||
|
||||
global_function& global_scope::add_function(std::string n, std::vector<std::string> ps, ast_ptr b) {
|
||||
global_function* new_function = new global_function(mangle_name(n), std::move(ps), std::move(b));
|
||||
global_function& global_scope::add_function(
|
||||
const std::string& n,
|
||||
std::vector<std::string> ps,
|
||||
ast_ptr b) {
|
||||
auto name = mng->new_mangled_name(n);
|
||||
global_function* new_function =
|
||||
new global_function(std::move(name), std::move(ps), std::move(b));
|
||||
functions.push_back(global_function_ptr(new_function));
|
||||
return *new_function;
|
||||
}
|
||||
|
||||
global_constructor& global_scope::add_constructor(std::string n, int8_t t, size_t a) {
|
||||
global_constructor* new_constructor = new global_constructor(mangle_name(n), t, a);
|
||||
global_constructor& global_scope::add_constructor(
|
||||
const std::string& n,
|
||||
int8_t t,
|
||||
size_t a) {
|
||||
auto name = mng->new_mangled_name(n);
|
||||
global_constructor* new_constructor = new global_constructor(name, t, a);
|
||||
constructors.push_back(global_constructor_ptr(new_constructor));
|
||||
return *new_constructor;
|
||||
}
|
||||
|
@ -65,19 +74,3 @@ void global_scope::generate_llvm(llvm_context& ctx) {
|
|||
function->generate_llvm(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
std::string global_scope::mangle_name(const std::string& n) {
|
||||
auto occurence_it = occurence_count.find(n);
|
||||
int occurence = 0;
|
||||
if(occurence_it != occurence_count.end()) {
|
||||
occurence = occurence_it->second + 1;
|
||||
}
|
||||
occurence_count[n] = occurence;
|
||||
|
||||
std::string final_name = n;
|
||||
if (occurence != 0) {
|
||||
final_name += "_";
|
||||
final_name += std::to_string(occurence);
|
||||
}
|
||||
return final_name;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <vector>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include "instruction.hpp"
|
||||
#include "mangler.hpp"
|
||||
|
||||
struct ast;
|
||||
using ast_ptr = std::unique_ptr<ast>;
|
||||
|
@ -40,16 +41,18 @@ struct global_constructor {
|
|||
using global_constructor_ptr = std::unique_ptr<global_constructor>;
|
||||
|
||||
struct global_scope {
|
||||
std::map<std::string, int> occurence_count;
|
||||
std::vector<global_function_ptr> functions;
|
||||
std::vector<global_constructor_ptr> constructors;
|
||||
mangler* mng;
|
||||
|
||||
global_function& add_function(std::string n, std::vector<std::string> ps, ast_ptr b);
|
||||
global_constructor& add_constructor(std::string n, int8_t t, size_t a);
|
||||
global_scope(mangler& m) : mng(&m) {}
|
||||
|
||||
global_function& add_function(
|
||||
const std::string& n,
|
||||
std::vector<std::string> ps,
|
||||
ast_ptr b);
|
||||
global_constructor& add_constructor(const std::string& n, int8_t t, size_t a);
|
||||
|
||||
void compile();
|
||||
void generate_llvm(llvm_context& ctx);
|
||||
|
||||
private:
|
||||
std::string mangle_name(const std::string& n);
|
||||
};
|
||||
|
|
199
13/main.cpp
199
13/main.cpp
|
@ -1,214 +1,27 @@
|
|||
#include "ast.hpp"
|
||||
#include <iostream>
|
||||
#include "binop.hpp"
|
||||
#include "definition.hpp"
|
||||
#include "graph.hpp"
|
||||
#include "instruction.hpp"
|
||||
#include "llvm_context.hpp"
|
||||
#include "parser.hpp"
|
||||
#include "compiler.hpp"
|
||||
#include "error.hpp"
|
||||
#include "type.hpp"
|
||||
#include "parse_driver.hpp"
|
||||
#include "type_env.hpp"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
void yy::parser::error(const yy::location& loc, const std::string& msg) {
|
||||
std::cerr << "An error occured: " << msg << std::endl;
|
||||
}
|
||||
|
||||
void prelude_types(definition_group& defs, type_env_ptr env) {
|
||||
type_ptr int_type = type_ptr(new type_internal("Int"));
|
||||
env->bind_type("Int", int_type);
|
||||
type_ptr int_type_app = type_ptr(new type_app(int_type));
|
||||
|
||||
type_ptr bool_type = type_ptr(new type_internal("Bool"));
|
||||
env->bind_type("Bool", bool_type);
|
||||
type_ptr bool_type_app = type_ptr(new type_app(bool_type));
|
||||
|
||||
type_ptr binop_type = type_ptr(new type_arr(
|
||||
int_type_app,
|
||||
type_ptr(new type_arr(int_type_app, int_type_app))));
|
||||
type_ptr cmp_type = type_ptr(new type_arr(
|
||||
int_type_app,
|
||||
type_ptr(new type_arr(int_type_app, bool_type_app))));
|
||||
|
||||
constexpr binop number_ops[] = { PLUS, MINUS, TIMES, DIVIDE, MODULO };
|
||||
constexpr binop cmp_ops[] = { EQUALS, LESS_EQUALS };
|
||||
for(auto& op : number_ops) {
|
||||
env->bind(op_name(op), binop_type, visibility::global);
|
||||
env->set_mangled_name(op_name(op), op_action(op));
|
||||
}
|
||||
for(auto& op : cmp_ops) {
|
||||
env->bind(op_name(op), cmp_type, visibility::global);
|
||||
env->set_mangled_name(op_name(op), op_action(op));
|
||||
}
|
||||
|
||||
env->bind("True", bool_type_app, visibility::global);
|
||||
env->bind("False", bool_type_app, visibility::global);
|
||||
}
|
||||
|
||||
void typecheck_program(
|
||||
definition_group& defs,
|
||||
type_mgr& mgr, type_env_ptr& env) {
|
||||
prelude_types(defs, env);
|
||||
|
||||
std::set<std::string> free;
|
||||
defs.find_free(free);
|
||||
defs.typecheck(mgr, env);
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
for(auto& pair : defs.env->names) {
|
||||
std::cout << pair.first << ": ";
|
||||
pair.second.type->print(mgr, std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
global_scope translate_program(definition_group& group) {
|
||||
global_scope scope;
|
||||
for(auto& data : group.defs_data) {
|
||||
data.second->into_globals(scope);
|
||||
}
|
||||
for(auto& defn : group.defs_defn) {
|
||||
auto& function = defn.second->into_global(scope);
|
||||
function.body->env->parent->set_mangled_name(defn.first, function.name);
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
|
||||
void output_llvm(llvm_context& ctx, const std::string& filename) {
|
||||
std::string targetTriple = llvm::sys::getDefaultTargetTriple();
|
||||
|
||||
llvm::InitializeNativeTarget();
|
||||
llvm::InitializeNativeTargetAsmParser();
|
||||
llvm::InitializeNativeTargetAsmPrinter();
|
||||
|
||||
std::string error;
|
||||
const llvm::Target* target =
|
||||
llvm::TargetRegistry::lookupTarget(targetTriple, error);
|
||||
if (!target) {
|
||||
std::cerr << error << std::endl;
|
||||
} else {
|
||||
std::string cpu = "generic";
|
||||
std::string features = "";
|
||||
llvm::TargetOptions options;
|
||||
std::unique_ptr<llvm::TargetMachine> targetMachine(
|
||||
target->createTargetMachine(targetTriple, cpu, features,
|
||||
options, llvm::Optional<llvm::Reloc::Model>()));
|
||||
|
||||
ctx.module.setDataLayout(targetMachine->createDataLayout());
|
||||
ctx.module.setTargetTriple(targetTriple);
|
||||
|
||||
std::error_code ec;
|
||||
llvm::raw_fd_ostream file(filename, ec, llvm::sys::fs::F_None);
|
||||
if (ec) {
|
||||
throw compiler_error("failed to open object file for writing");
|
||||
} else {
|
||||
llvm::CodeGenFileType type = llvm::CGFT_ObjectFile;
|
||||
llvm::legacy::PassManager pm;
|
||||
if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) {
|
||||
throw compiler_error("failed to add passes to pass manager");
|
||||
} else {
|
||||
pm.run(ctx.module);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gen_llvm_internal_op(llvm_context& ctx, binop op) {
|
||||
auto new_function = ctx.create_custom_function(op_action(op), 2);
|
||||
std::vector<instruction_ptr> instructions;
|
||||
instructions.push_back(instruction_ptr(new instruction_push(1)));
|
||||
instructions.push_back(instruction_ptr(new instruction_eval()));
|
||||
instructions.push_back(instruction_ptr(new instruction_push(1)));
|
||||
instructions.push_back(instruction_ptr(new instruction_eval()));
|
||||
instructions.push_back(instruction_ptr(new instruction_binop(op)));
|
||||
instructions.push_back(instruction_ptr(new instruction_update(2)));
|
||||
instructions.push_back(instruction_ptr(new instruction_pop(2)));
|
||||
ctx.builder.SetInsertPoint(&new_function->getEntryBlock());
|
||||
for(auto& instruction : instructions) {
|
||||
instruction->gen_llvm(ctx, new_function);
|
||||
}
|
||||
ctx.builder.CreateRetVoid();
|
||||
}
|
||||
|
||||
void gen_llvm_boolean_constructor(llvm_context& ctx, const std::string& s, bool b) {
|
||||
auto new_function = ctx.create_custom_function(s, 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.builder.SetInsertPoint(&new_function->getEntryBlock());
|
||||
for(auto& instruction : instructions) {
|
||||
instruction->gen_llvm(ctx, new_function);
|
||||
}
|
||||
ctx.builder.CreateRetVoid();
|
||||
}
|
||||
|
||||
void gen_llvm(global_scope& scope) {
|
||||
llvm_context ctx;
|
||||
gen_llvm_internal_op(ctx, PLUS);
|
||||
gen_llvm_internal_op(ctx, MINUS);
|
||||
gen_llvm_internal_op(ctx, TIMES);
|
||||
gen_llvm_internal_op(ctx, DIVIDE);
|
||||
gen_llvm_internal_op(ctx, MODULO);
|
||||
gen_llvm_internal_op(ctx, EQUALS);
|
||||
gen_llvm_internal_op(ctx, LESS_EQUALS);
|
||||
gen_llvm_boolean_constructor(ctx, "True", true);
|
||||
gen_llvm_boolean_constructor(ctx, "False", false);
|
||||
|
||||
scope.generate_llvm(ctx);
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
ctx.module.print(llvm::outs(), nullptr);
|
||||
#endif
|
||||
|
||||
output_llvm(ctx, "program.o");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if(argc != 2) {
|
||||
std::cerr << "please enter a file to compile." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
parse_driver driver(argv[1]);
|
||||
if(!driver.run_parse()) {
|
||||
std::cerr << "failed to parse file " << argv[1] << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
type_mgr mgr;
|
||||
type_env_ptr env(new type_env);
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
for(auto& def_defn : driver.global_defs.defs_defn) {
|
||||
std::cout << def_defn.second->name;
|
||||
for(auto& param : def_defn.second->params) std::cout << " " << param;
|
||||
std::cout << ":" << std::endl;
|
||||
def_defn.second->body->print(1, std::cout);
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
compiler cmp(argv[1]);
|
||||
|
||||
try {
|
||||
typecheck_program(driver.global_defs, mgr, env);
|
||||
global_scope scope = translate_program(driver.global_defs);
|
||||
scope.compile();
|
||||
gen_llvm(scope);
|
||||
cmp("program.o");
|
||||
} catch(unification_error& err) {
|
||||
err.pretty_print(std::cerr, driver, mgr);
|
||||
err.pretty_print(std::cerr, cmp.get_file_manager(), cmp.get_type_manager());
|
||||
} catch(type_error& err) {
|
||||
err.pretty_print(std::cerr, driver);
|
||||
err.pretty_print(std::cerr, cmp.get_file_manager());
|
||||
} catch (compiler_error& err) {
|
||||
err.pretty_print(std::cerr, driver);
|
||||
err.pretty_print(std::cerr, cmp.get_file_manager());
|
||||
}
|
||||
}
|
||||
|
|
17
13/mangler.cpp
Normal file
17
13/mangler.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include "mangler.hpp"
|
||||
|
||||
std::string mangler::new_mangled_name(const std::string& n) {
|
||||
auto occurence_it = occurence_count.find(n);
|
||||
int occurence = 0;
|
||||
if(occurence_it != occurence_count.end()) {
|
||||
occurence = occurence_it->second + 1;
|
||||
}
|
||||
occurence_count[n] = occurence;
|
||||
|
||||
std::string final_name = n;
|
||||
if (occurence != 0) {
|
||||
final_name += "_";
|
||||
final_name += std::to_string(occurence);
|
||||
}
|
||||
return final_name;
|
||||
}
|
9
13/mangler.hpp
Normal file
9
13/mangler.hpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
struct mangler {
|
||||
std::map<std::string, int> occurence_count;
|
||||
|
||||
std::string new_mangled_name(const std::string& str);
|
||||
};
|
|
@ -2,44 +2,37 @@
|
|||
#include "scanner.hpp"
|
||||
#include <sstream>
|
||||
|
||||
bool parse_driver::run_parse() {
|
||||
FILE* stream = fopen(file_name.c_str(), "r");
|
||||
if(!stream) return false;
|
||||
file_mgr::file_mgr() : file_offset(0) {
|
||||
line_offsets.push_back(0);
|
||||
yyscan_t scanner;
|
||||
yylex_init(&scanner);
|
||||
yyset_in(stream, scanner);
|
||||
yy::parser parser(scanner, *this);
|
||||
parser();
|
||||
yylex_destroy(scanner);
|
||||
fclose(stream);
|
||||
file_contents = string_stream.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
void parse_driver::write(const char* buf, size_t len) {
|
||||
void file_mgr::write(const char* buf, size_t len) {
|
||||
string_stream.write(buf, len);
|
||||
file_offset += len;
|
||||
}
|
||||
|
||||
void parse_driver::mark_line() {
|
||||
void file_mgr::mark_line() {
|
||||
line_offsets.push_back(file_offset);
|
||||
}
|
||||
|
||||
size_t parse_driver::get_index(int line, int column) {
|
||||
assert(line > 0 && line <= line_offsets.size());
|
||||
return line_offsets[line-1] + column - 1;
|
||||
void file_mgr::finalize() {
|
||||
file_contents = string_stream.str();
|
||||
}
|
||||
|
||||
size_t parse_driver::get_line_end(int line) {
|
||||
size_t file_mgr::get_index(int line, int column) const {
|
||||
assert(line > 0 && line <= line_offsets.size());
|
||||
return line_offsets.at(line-1) + column - 1;
|
||||
}
|
||||
|
||||
size_t file_mgr::get_line_end(int line) const {
|
||||
if(line == line_offsets.size()) return file_contents.size();
|
||||
return get_index(line+1, 1);
|
||||
}
|
||||
|
||||
void parse_driver::print_location(
|
||||
void file_mgr::print_location(
|
||||
std::ostream& stream,
|
||||
const yy::location& loc,
|
||||
bool highlight) {
|
||||
bool highlight) const {
|
||||
size_t print_start = get_index(loc.begin.line, 1);
|
||||
size_t highlight_start = get_index(loc.begin.line, loc.begin.column);
|
||||
size_t highlight_end = get_index(loc.end.line, loc.end.column);
|
||||
|
@ -51,3 +44,29 @@ void parse_driver::print_location(
|
|||
if(highlight) stream << "\033[0m";
|
||||
stream.write(content + highlight_end, print_end - highlight_end);
|
||||
}
|
||||
|
||||
bool parse_driver::run_parse() {
|
||||
FILE* stream = fopen(file_name.c_str(), "r");
|
||||
if(!stream) return false;
|
||||
yyscan_t scanner;
|
||||
yylex_init(&scanner);
|
||||
yyset_in(stream, scanner);
|
||||
yy::parser parser(scanner, *this);
|
||||
parser();
|
||||
yylex_destroy(scanner);
|
||||
fclose(stream);
|
||||
file_m->finalize();
|
||||
return true;
|
||||
}
|
||||
|
||||
yy::location& parse_driver::get_current_location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
file_mgr& parse_driver::get_file_manager() const {
|
||||
return *file_m;
|
||||
}
|
||||
|
||||
definition_group& parse_driver::get_global_defs() const {
|
||||
return *global_defs;
|
||||
}
|
||||
|
|
|
@ -11,29 +11,46 @@ struct parse_driver;
|
|||
void scanner_init(parse_driver* d, yyscan_t* scanner);
|
||||
void scanner_destroy(yyscan_t* scanner);
|
||||
|
||||
struct parse_driver {
|
||||
std::string file_name;
|
||||
std::ostringstream string_stream;
|
||||
std::string file_contents;
|
||||
class file_mgr {
|
||||
private:
|
||||
std::ostringstream string_stream;
|
||||
std::string file_contents;
|
||||
|
||||
yy::location location;
|
||||
size_t file_offset;
|
||||
std::vector<size_t> line_offsets;
|
||||
size_t file_offset;
|
||||
std::vector<size_t> line_offsets;
|
||||
public:
|
||||
file_mgr();
|
||||
|
||||
definition_group global_defs;
|
||||
void write(const char* buffer, size_t len);
|
||||
void mark_line();
|
||||
void finalize();
|
||||
|
||||
parse_driver(const std::string& file)
|
||||
: file_name(file), file_offset(0) {}
|
||||
size_t get_index(int line, int column) const;
|
||||
size_t get_line_end(int line) const;
|
||||
void print_location(
|
||||
std::ostream& stream,
|
||||
const yy::location& loc,
|
||||
bool highlight = true) const;
|
||||
};
|
||||
|
||||
class parse_driver {
|
||||
private:
|
||||
std::string file_name;
|
||||
yy::location location;
|
||||
definition_group* global_defs;
|
||||
file_mgr* file_m;
|
||||
|
||||
public:
|
||||
parse_driver(
|
||||
file_mgr& mgr,
|
||||
definition_group& defs,
|
||||
const std::string& file)
|
||||
: file_name(file), file_m(&mgr), global_defs(&defs) {}
|
||||
|
||||
bool run_parse();
|
||||
void write(const char* buff, size_t len);
|
||||
void mark_line();
|
||||
size_t get_index(int line, int column);
|
||||
size_t get_line_end(int line);
|
||||
void print_location(
|
||||
std::ostream& stream,
|
||||
const yy::location& loc,
|
||||
bool highlight = true);
|
||||
yy::location& get_current_location();
|
||||
file_mgr& get_file_manager() const;
|
||||
definition_group& get_global_defs() const;
|
||||
};
|
||||
|
||||
#define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv)
|
||||
|
|
|
@ -68,7 +68,7 @@ using yyscan_t = void*;
|
|||
%%
|
||||
|
||||
program
|
||||
: definitions { $1.vis = visibility::global; std::swap(drv.global_defs, $1); }
|
||||
: definitions { $1.vis = visibility::global; std::swap(drv.get_global_defs(), $1); }
|
||||
;
|
||||
|
||||
definitions
|
||||
|
|
492
13/scanner.hpp
Normal file
492
13/scanner.hpp
Normal file
|
@ -0,0 +1,492 @@
|
|||
#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 */
|
59
13/scanner.l
59
13/scanner.l
|
@ -9,38 +9,41 @@
|
|||
#include "parse_driver.hpp"
|
||||
#include "parser.hpp"
|
||||
|
||||
#define YY_USER_ACTION drv.write(yytext, yyleng); drv.location.step(); drv.location.columns(yyleng);
|
||||
#define YY_USER_ACTION \
|
||||
drv.get_file_manager().write(yytext, yyleng); \
|
||||
LOC.step(); LOC.columns(yyleng);
|
||||
#define LOC drv.get_current_location()
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
\n { drv.location.lines(); drv.mark_line(); }
|
||||
\n { drv.get_current_location().lines(); drv.get_file_manager().mark_line(); }
|
||||
[ ]+ {}
|
||||
\\ { return yy::parser::make_BACKSLASH(drv.location); }
|
||||
\+ { return yy::parser::make_PLUS(drv.location); }
|
||||
\* { return yy::parser::make_TIMES(drv.location); }
|
||||
- { return yy::parser::make_MINUS(drv.location); }
|
||||
\/ { return yy::parser::make_DIVIDE(drv.location); }
|
||||
% { return yy::parser::make_MODULO(drv.location); }
|
||||
== { return yy::parser::make_EQUALS(drv.location); }
|
||||
\<= { return yy::parser::make_LESS_EQUALS(drv.location); }
|
||||
` { return yy::parser::make_BACKTICK(drv.location); }
|
||||
[0-9]+ { return yy::parser::make_INT(atoi(yytext), drv.location); }
|
||||
defn { return yy::parser::make_DEFN(drv.location); }
|
||||
data { return yy::parser::make_DATA(drv.location); }
|
||||
case { return yy::parser::make_CASE(drv.location); }
|
||||
of { return yy::parser::make_OF(drv.location); }
|
||||
let { return yy::parser::make_LET(drv.location); }
|
||||
in { return yy::parser::make_IN(drv.location); }
|
||||
\{ { return yy::parser::make_OCURLY(drv.location); }
|
||||
\} { return yy::parser::make_CCURLY(drv.location); }
|
||||
\( { return yy::parser::make_OPAREN(drv.location); }
|
||||
\) { return yy::parser::make_CPAREN(drv.location); }
|
||||
, { return yy::parser::make_COMMA(drv.location); }
|
||||
-> { return yy::parser::make_ARROW(drv.location); }
|
||||
= { return yy::parser::make_EQUAL(drv.location); }
|
||||
[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext), drv.location); }
|
||||
[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext), drv.location); }
|
||||
<<EOF>> { return yy::parser::make_YYEOF(drv.location); }
|
||||
\\ { return yy::parser::make_BACKSLASH(LOC); }
|
||||
\+ { return yy::parser::make_PLUS(LOC); }
|
||||
\* { return yy::parser::make_TIMES(LOC); }
|
||||
- { return yy::parser::make_MINUS(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); }
|
||||
defn { return yy::parser::make_DEFN(LOC); }
|
||||
data { return yy::parser::make_DATA(LOC); }
|
||||
case { return yy::parser::make_CASE(LOC); }
|
||||
of { return yy::parser::make_OF(LOC); }
|
||||
let { return yy::parser::make_LET(LOC); }
|
||||
in { return yy::parser::make_IN(LOC); }
|
||||
\{ { return yy::parser::make_OCURLY(LOC); }
|
||||
\} { return yy::parser::make_CCURLY(LOC); }
|
||||
\( { return yy::parser::make_OPAREN(LOC); }
|
||||
\) { return yy::parser::make_CPAREN(LOC); }
|
||||
, { return yy::parser::make_COMMA(LOC); }
|
||||
-> { return yy::parser::make_ARROW(LOC); }
|
||||
= { return yy::parser::make_EQUAL(LOC); }
|
||||
[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext), LOC); }
|
||||
[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext), LOC); }
|
||||
<<EOF>> { return yy::parser::make_YYEOF(LOC); }
|
||||
|
||||
%%
|
||||
|
|
|
@ -44,8 +44,7 @@ void type_env::set_mangled_name(const std::string& name, const std::string& mang
|
|||
|
||||
const std::string& type_env::get_mangled_name(const std::string& name) const {
|
||||
auto it = names.find(name);
|
||||
if(it != names.end())
|
||||
return (it->second.mangled_name != "") ? it->second.mangled_name : name;
|
||||
if(it != names.end()) return it->second.mangled_name;
|
||||
assert(parent != nullptr);
|
||||
return parent->get_mangled_name(name);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user