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
|
graph.cpp graph.hpp
|
||||||
global_scope.cpp global_scope.hpp
|
global_scope.cpp global_scope.hpp
|
||||||
parse_driver.cpp parse_driver.hpp
|
parse_driver.cpp parse_driver.hpp
|
||||||
|
mangler.cpp mangler.hpp
|
||||||
|
compiler.cpp compiler.hpp
|
||||||
${BISON_parser_OUTPUTS}
|
${BISON_parser_OUTPUTS}
|
||||||
${FLEX_scanner_OUTPUTS}
|
${FLEX_scanner_OUTPUTS}
|
||||||
main.cpp
|
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 {
|
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
|
||||||
into.push_back(instruction_ptr(
|
into.push_back(instruction_ptr(
|
||||||
(this->env->is_global(id)) ?
|
(this->env->is_global(id)) ?
|
||||||
(instruction*) new instruction_pushglobal(id) :
|
(instruction*) new instruction_pushglobal(this->env->get_mangled_name(id)) :
|
||||||
(instruction*) new instruction_push(
|
(instruction*) new instruction_push(env->get_offset(id))));
|
||||||
env->get_offset(this->env->get_mangled_name(id)))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ast_uid::print(int indent, std::ostream& to) const {
|
void ast_uid::print(int indent, std::ostream& to) const {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
enum binop {
|
enum binop {
|
||||||
|
@ -11,5 +12,10 @@ enum binop {
|
||||||
LESS_EQUALS,
|
LESS_EQUALS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr binop all_binops[] = {
|
||||||
|
PLUS, MINUS, TIMES, DIVIDE, MODULO,
|
||||||
|
EQUALS, LESS_EQUALS
|
||||||
|
};
|
||||||
|
|
||||||
std::string op_name(binop op);
|
std::string op_name(binop op);
|
||||||
std::string op_action(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;
|
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;
|
if(!loc) return;
|
||||||
to << "occuring on line " << loc->begin.line << ":" << std::endl;
|
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_about(to);
|
||||||
print_location(to, drv);
|
print_location(to, fm);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* type_error::what() const noexcept {
|
const char* type_error::what() const noexcept {
|
||||||
return "an error occured while checking the types of the program";
|
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_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) {
|
void unification_error::pretty_print(std::ostream& to, file_mgr& fm, type_mgr& mgr) {
|
||||||
type_error::pretty_print(to, drv);
|
type_error::pretty_print(to, fm);
|
||||||
to << "the expected type was:" << std::endl;
|
to << "the expected type was:" << std::endl;
|
||||||
to << " \033[34m";
|
to << " \033[34m";
|
||||||
left->print(mgr, to);
|
left->print(mgr, to);
|
||||||
|
|
|
@ -17,9 +17,9 @@ struct compiler_error : std::exception {
|
||||||
const char* what() const noexcept override;
|
const char* what() const noexcept override;
|
||||||
|
|
||||||
void print_about(std::ostream& to);
|
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 {
|
struct type_error : compiler_error {
|
||||||
|
@ -29,7 +29,7 @@ struct type_error : compiler_error {
|
||||||
: compiler_error(std::move(d), std::move(l)) {}
|
: compiler_error(std::move(d), std::move(l)) {}
|
||||||
|
|
||||||
const char* what() const noexcept override;
|
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 {
|
struct unification_error : public type_error {
|
||||||
|
@ -40,5 +40,5 @@ struct unification_error : public type_error {
|
||||||
: left(std::move(l)), right(std::move(r)),
|
: left(std::move(l)), right(std::move(r)),
|
||||||
type_error("failed to unify types", std::move(loc)) {}
|
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();
|
ctx.builder.CreateRetVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
global_function& global_scope::add_function(std::string n, std::vector<std::string> ps, ast_ptr b) {
|
global_function& global_scope::add_function(
|
||||||
global_function* new_function = new global_function(mangle_name(n), std::move(ps), std::move(b));
|
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));
|
functions.push_back(global_function_ptr(new_function));
|
||||||
return *new_function;
|
return *new_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
global_constructor& global_scope::add_constructor(std::string n, int8_t t, size_t a) {
|
global_constructor& global_scope::add_constructor(
|
||||||
global_constructor* new_constructor = new global_constructor(mangle_name(n), t, a);
|
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));
|
constructors.push_back(global_constructor_ptr(new_constructor));
|
||||||
return *new_constructor;
|
return *new_constructor;
|
||||||
}
|
}
|
||||||
|
@ -65,19 +74,3 @@ void global_scope::generate_llvm(llvm_context& ctx) {
|
||||||
function->generate_llvm(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 <vector>
|
||||||
#include <llvm/IR/Function.h>
|
#include <llvm/IR/Function.h>
|
||||||
#include "instruction.hpp"
|
#include "instruction.hpp"
|
||||||
|
#include "mangler.hpp"
|
||||||
|
|
||||||
struct ast;
|
struct ast;
|
||||||
using ast_ptr = std::unique_ptr<ast>;
|
using ast_ptr = std::unique_ptr<ast>;
|
||||||
|
@ -40,16 +41,18 @@ struct global_constructor {
|
||||||
using global_constructor_ptr = std::unique_ptr<global_constructor>;
|
using global_constructor_ptr = std::unique_ptr<global_constructor>;
|
||||||
|
|
||||||
struct global_scope {
|
struct global_scope {
|
||||||
std::map<std::string, int> occurence_count;
|
|
||||||
std::vector<global_function_ptr> functions;
|
std::vector<global_function_ptr> functions;
|
||||||
std::vector<global_constructor_ptr> constructors;
|
std::vector<global_constructor_ptr> constructors;
|
||||||
|
mangler* mng;
|
||||||
|
|
||||||
global_function& add_function(std::string n, std::vector<std::string> ps, ast_ptr b);
|
global_scope(mangler& m) : mng(&m) {}
|
||||||
global_constructor& add_constructor(std::string n, int8_t t, size_t a);
|
|
||||||
|
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 compile();
|
||||||
void generate_llvm(llvm_context& ctx);
|
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 "ast.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "binop.hpp"
|
|
||||||
#include "definition.hpp"
|
|
||||||
#include "graph.hpp"
|
|
||||||
#include "instruction.hpp"
|
|
||||||
#include "llvm_context.hpp"
|
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
|
#include "compiler.hpp"
|
||||||
#include "error.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) {
|
void yy::parser::error(const yy::location& loc, const std::string& msg) {
|
||||||
std::cerr << "An error occured: " << msg << std::endl;
|
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) {
|
int main(int argc, char** argv) {
|
||||||
if(argc != 2) {
|
if(argc != 2) {
|
||||||
std::cerr << "please enter a file to compile." << std::endl;
|
std::cerr << "please enter a file to compile." << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
parse_driver driver(argv[1]);
|
compiler cmp(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
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
typecheck_program(driver.global_defs, mgr, env);
|
cmp("program.o");
|
||||||
global_scope scope = translate_program(driver.global_defs);
|
|
||||||
scope.compile();
|
|
||||||
gen_llvm(scope);
|
|
||||||
} catch(unification_error& err) {
|
} 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) {
|
} catch(type_error& err) {
|
||||||
err.pretty_print(std::cerr, driver);
|
err.pretty_print(std::cerr, cmp.get_file_manager());
|
||||||
} catch (compiler_error& err) {
|
} 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 "scanner.hpp"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
bool parse_driver::run_parse() {
|
file_mgr::file_mgr() : file_offset(0) {
|
||||||
FILE* stream = fopen(file_name.c_str(), "r");
|
|
||||||
if(!stream) return false;
|
|
||||||
line_offsets.push_back(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);
|
string_stream.write(buf, len);
|
||||||
file_offset += len;
|
file_offset += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_driver::mark_line() {
|
void file_mgr::mark_line() {
|
||||||
line_offsets.push_back(file_offset);
|
line_offsets.push_back(file_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t parse_driver::get_index(int line, int column) {
|
void file_mgr::finalize() {
|
||||||
assert(line > 0 && line <= line_offsets.size());
|
file_contents = string_stream.str();
|
||||||
return line_offsets[line-1] + column - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
if(line == line_offsets.size()) return file_contents.size();
|
||||||
return get_index(line+1, 1);
|
return get_index(line+1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_driver::print_location(
|
void file_mgr::print_location(
|
||||||
std::ostream& stream,
|
std::ostream& stream,
|
||||||
const yy::location& loc,
|
const yy::location& loc,
|
||||||
bool highlight) {
|
bool highlight) const {
|
||||||
size_t print_start = get_index(loc.begin.line, 1);
|
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_start = get_index(loc.begin.line, loc.begin.column);
|
||||||
size_t highlight_end = get_index(loc.end.line, loc.end.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";
|
if(highlight) stream << "\033[0m";
|
||||||
stream.write(content + highlight_end, print_end - highlight_end);
|
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_init(parse_driver* d, yyscan_t* scanner);
|
||||||
void scanner_destroy(yyscan_t* scanner);
|
void scanner_destroy(yyscan_t* scanner);
|
||||||
|
|
||||||
struct parse_driver {
|
class file_mgr {
|
||||||
std::string file_name;
|
private:
|
||||||
std::ostringstream string_stream;
|
std::ostringstream string_stream;
|
||||||
std::string file_contents;
|
std::string file_contents;
|
||||||
|
|
||||||
yy::location location;
|
size_t file_offset;
|
||||||
size_t file_offset;
|
std::vector<size_t> line_offsets;
|
||||||
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)
|
size_t get_index(int line, int column) const;
|
||||||
: file_name(file), file_offset(0) {}
|
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();
|
bool run_parse();
|
||||||
void write(const char* buff, size_t len);
|
yy::location& get_current_location();
|
||||||
void mark_line();
|
file_mgr& get_file_manager() const;
|
||||||
size_t get_index(int line, int column);
|
definition_group& get_global_defs() const;
|
||||||
size_t get_line_end(int line);
|
|
||||||
void print_location(
|
|
||||||
std::ostream& stream,
|
|
||||||
const yy::location& loc,
|
|
||||||
bool highlight = true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv)
|
#define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv)
|
||||||
|
|
|
@ -68,7 +68,7 @@ using yyscan_t = void*;
|
||||||
%%
|
%%
|
||||||
|
|
||||||
program
|
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
|
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 "parse_driver.hpp"
|
||||||
#include "parser.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_BACKSLASH(LOC); }
|
||||||
\+ { return yy::parser::make_PLUS(drv.location); }
|
\+ { return yy::parser::make_PLUS(LOC); }
|
||||||
\* { return yy::parser::make_TIMES(drv.location); }
|
\* { return yy::parser::make_TIMES(LOC); }
|
||||||
- { return yy::parser::make_MINUS(drv.location); }
|
- { return yy::parser::make_MINUS(LOC); }
|
||||||
\/ { return yy::parser::make_DIVIDE(drv.location); }
|
\/ { return yy::parser::make_DIVIDE(LOC); }
|
||||||
% { return yy::parser::make_MODULO(drv.location); }
|
% { return yy::parser::make_MODULO(LOC); }
|
||||||
== { return yy::parser::make_EQUALS(drv.location); }
|
== { return yy::parser::make_EQUALS(LOC); }
|
||||||
\<= { return yy::parser::make_LESS_EQUALS(drv.location); }
|
\<= { return yy::parser::make_LESS_EQUALS(LOC); }
|
||||||
` { return yy::parser::make_BACKTICK(drv.location); }
|
` { return yy::parser::make_BACKTICK(LOC); }
|
||||||
[0-9]+ { return yy::parser::make_INT(atoi(yytext), drv.location); }
|
[0-9]+ { return yy::parser::make_INT(atoi(yytext), LOC); }
|
||||||
defn { return yy::parser::make_DEFN(drv.location); }
|
defn { return yy::parser::make_DEFN(LOC); }
|
||||||
data { return yy::parser::make_DATA(drv.location); }
|
data { return yy::parser::make_DATA(LOC); }
|
||||||
case { return yy::parser::make_CASE(drv.location); }
|
case { return yy::parser::make_CASE(LOC); }
|
||||||
of { return yy::parser::make_OF(drv.location); }
|
of { return yy::parser::make_OF(LOC); }
|
||||||
let { return yy::parser::make_LET(drv.location); }
|
let { return yy::parser::make_LET(LOC); }
|
||||||
in { return yy::parser::make_IN(drv.location); }
|
in { return yy::parser::make_IN(LOC); }
|
||||||
\{ { return yy::parser::make_OCURLY(drv.location); }
|
\{ { return yy::parser::make_OCURLY(LOC); }
|
||||||
\} { return yy::parser::make_CCURLY(drv.location); }
|
\} { return yy::parser::make_CCURLY(LOC); }
|
||||||
\( { return yy::parser::make_OPAREN(drv.location); }
|
\( { return yy::parser::make_OPAREN(LOC); }
|
||||||
\) { return yy::parser::make_CPAREN(drv.location); }
|
\) { return yy::parser::make_CPAREN(LOC); }
|
||||||
, { return yy::parser::make_COMMA(drv.location); }
|
, { return yy::parser::make_COMMA(LOC); }
|
||||||
-> { return yy::parser::make_ARROW(drv.location); }
|
-> { return yy::parser::make_ARROW(LOC); }
|
||||||
= { return yy::parser::make_EQUAL(drv.location); }
|
= { return yy::parser::make_EQUAL(LOC); }
|
||||||
[a-z][a-zA-Z]* { return yy::parser::make_LID(std::string(yytext), drv.location); }
|
[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), drv.location); }
|
[A-Z][a-zA-Z]* { return yy::parser::make_UID(std::string(yytext), LOC); }
|
||||||
<<EOF>> { return yy::parser::make_YYEOF(drv.location); }
|
<<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 {
|
const std::string& type_env::get_mangled_name(const std::string& name) const {
|
||||||
auto it = names.find(name);
|
auto it = names.find(name);
|
||||||
if(it != names.end())
|
if(it != names.end()) return it->second.mangled_name;
|
||||||
return (it->second.mangled_name != "") ? it->second.mangled_name : name;
|
|
||||||
assert(parent != nullptr);
|
assert(parent != nullptr);
|
||||||
return parent->get_mangled_name(name);
|
return parent->get_mangled_name(name);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user