Continue implementation of compilation

This commit is contained in:
Danila Fedorin 2019-10-01 23:23:52 -07:00
parent 64f4abb8d6
commit d9c151d774
8 changed files with 111 additions and 16 deletions

View File

@ -18,6 +18,7 @@ add_executable(compiler
env.cpp env.hpp env.cpp env.hpp
type.cpp type.hpp type.cpp type.hpp
error.cpp error.hpp error.cpp error.hpp
binop.cpp binop.hpp
${BISON_parser_OUTPUTS} ${BISON_parser_OUTPUTS}
${FLEX_scanner_OUTPUTS} ${FLEX_scanner_OUTPUTS}
main.cpp main.cpp

View File

@ -2,16 +2,6 @@
#include <ostream> #include <ostream>
#include "error.hpp" #include "error.hpp"
std::string op_name(binop op) {
switch(op) {
case PLUS: return "+";
case MINUS: return "-";
case TIMES: return "*";
case DIVIDE: return "/";
}
return "??";
}
void print_indent(int n, std::ostream& to) { void print_indent(int n, std::ostream& to) {
while(n--) to << " "; while(n--) to << " ";
} }
@ -25,6 +15,10 @@ type_ptr ast_int::typecheck(type_mgr& mgr, const type_env& env) const {
return type_ptr(new type_base("Int")); return type_ptr(new type_base("Int"));
} }
void ast_int::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(new instruction_pushint(value)));
}
void ast_lid::print(int indent, std::ostream& to) const { void ast_lid::print(int indent, std::ostream& to) const {
print_indent(indent, to); print_indent(indent, to);
to << "LID: " << id << std::endl; to << "LID: " << id << std::endl;
@ -34,6 +28,10 @@ type_ptr ast_lid::typecheck(type_mgr& mgr, const type_env& env) const {
return env.lookup(id); return env.lookup(id);
} }
void ast_lid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(new instruction_pushglobal(id)));
}
void ast_uid::print(int indent, std::ostream& to) const { void ast_uid::print(int indent, std::ostream& to) const {
print_indent(indent, to); print_indent(indent, to);
to << "UID: " << id << std::endl; to << "UID: " << id << std::endl;
@ -43,6 +41,13 @@ type_ptr ast_uid::typecheck(type_mgr& mgr, const type_env& env) const {
return env.lookup(id); return env.lookup(id);
} }
void ast_uid::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
into.push_back(instruction_ptr(
env->has_variable(id) ?
(instruction*) new instruction_push(env->get_offset(id)) :
(instruction*) new instruction_pushglobal(id)));
}
void ast_binop::print(int indent, std::ostream& to) const { void ast_binop::print(int indent, std::ostream& to) const {
print_indent(indent, to); print_indent(indent, to);
to << "BINOP: " << op_name(op) << std::endl; to << "BINOP: " << op_name(op) << std::endl;
@ -64,6 +69,14 @@ type_ptr ast_binop::typecheck(type_mgr& mgr, const type_env& env) const {
return return_type; return return_type;
} }
void ast_binop::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
left->compile(env, into);
right->compile(env, into);
into.push_back(instruction_ptr(new instruction_pushglobal(op_name(op))));
into.push_back(instruction_ptr(new instruction_mkapp()));
into.push_back(instruction_ptr(new instruction_mkapp()));
}
void ast_app::print(int indent, std::ostream& to) const { void ast_app::print(int indent, std::ostream& to) const {
print_indent(indent, to); print_indent(indent, to);
to << "APP:" << std::endl; to << "APP:" << std::endl;
@ -81,6 +94,12 @@ type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const {
return return_type; return return_type;
} }
void ast_app::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
left->compile(env, into);
right->compile(env, into);
into.push_back(instruction_ptr(new instruction_mkapp()));
}
void ast_case::print(int indent, std::ostream& to) const { void ast_case::print(int indent, std::ostream& to) const {
print_indent(indent, to); print_indent(indent, to);
to << "CASE: " << std::endl; to << "CASE: " << std::endl;
@ -111,6 +130,10 @@ type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const {
return branch_type; return branch_type;
} }
void ast_case::compile(const env_ptr& env, std::vector<instruction_ptr>& into) const {
}
void pattern_var::print(std::ostream& to) const { void pattern_var::print(std::ostream& to) const {
to << var; to << var;
} }

View File

@ -12,8 +12,8 @@ struct ast {
virtual void print(int indent, std::ostream& to) const = 0; virtual void print(int indent, std::ostream& to) const = 0;
virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0; virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0;
virtual void compile(const env_ptr env, virtual void compile(const env_ptr& env,
std::vector<instruction>& into) const; std::vector<instruction_ptr>& into) const = 0;
}; };
using ast_ptr = std::unique_ptr<ast>; using ast_ptr = std::unique_ptr<ast>;
@ -64,6 +64,7 @@ struct ast_int : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
type_ptr typecheck(type_mgr& mgr, const type_env& env) const; type_ptr typecheck(type_mgr& mgr, const type_env& env) const;
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
struct ast_lid : public ast { struct ast_lid : public ast {
@ -74,6 +75,7 @@ struct ast_lid : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
type_ptr typecheck(type_mgr& mgr, const type_env& env) const; type_ptr typecheck(type_mgr& mgr, const type_env& env) const;
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
struct ast_uid : public ast { struct ast_uid : public ast {
@ -84,6 +86,7 @@ struct ast_uid : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
type_ptr typecheck(type_mgr& mgr, const type_env& env) const; type_ptr typecheck(type_mgr& mgr, const type_env& env) const;
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
struct ast_binop : public ast { struct ast_binop : public ast {
@ -96,6 +99,7 @@ struct ast_binop : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
type_ptr typecheck(type_mgr& mgr, const type_env& env) const; type_ptr typecheck(type_mgr& mgr, const type_env& env) const;
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
struct ast_app : public ast { struct ast_app : public ast {
@ -107,6 +111,7 @@ struct ast_app : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
type_ptr typecheck(type_mgr& mgr, const type_env& env) const; type_ptr typecheck(type_mgr& mgr, const type_env& env) const;
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
struct ast_case : public ast { struct ast_case : public ast {
@ -118,6 +123,7 @@ struct ast_case : public ast {
void print(int indent, std::ostream& to) const; void print(int indent, std::ostream& to) const;
type_ptr typecheck(type_mgr& mgr, const type_env& env) const; type_ptr typecheck(type_mgr& mgr, const type_env& env) const;
void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
}; };
struct pattern_var : public pattern { struct pattern_var : public pattern {

View File

@ -0,0 +1,21 @@
#include "binop.hpp"
std::string op_name(binop op) {
switch(op) {
case PLUS: return "+";
case MINUS: return "-";
case TIMES: return "*";
case DIVIDE: return "/";
}
return "??";
}
std::string op_action(binop op) {
switch(op) {
case PLUS: return "plus";
case MINUS: return "minus";
case TIMES: return "times";
case DIVIDE: return "divide";
}
return "??";
}

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <string>
enum binop { enum binop {
PLUS, PLUS,
@ -7,3 +8,5 @@ enum binop {
DIVIDE DIVIDE
}; };
std::string op_name(binop op);
std::string op_action(binop op);

23
code/compiler/06/env.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "env.hpp"
int env_var::get_offset(const std::string& name) const {
if(name == this->name) return 0;
if(parent) return parent->get_offset(name) + 1;
throw 0;
}
bool env_var::has_variable(const std::string& name) const {
if(name == this->name) return true;
if(parent) return parent->has_variable(name);
return false;
}
int env_offset::get_offset(const std::string& name) const {
if(parent) return parent->get_offset(name) + offset;
throw 0;
}
bool env_offset::has_variable(const std::string& name) const {
if(parent) return parent->has_variable(name);
return false;
}

View File

@ -6,6 +6,7 @@ struct env {
virtual ~env() = default; virtual ~env() = default;
virtual int get_offset(const std::string& name) const = 0; virtual int get_offset(const std::string& name) const = 0;
virtual bool has_variable(const std::string& name) const = 0;
}; };
using env_ptr = std::shared_ptr<env>; using env_ptr = std::shared_ptr<env>;
@ -17,7 +18,8 @@ struct env_var {
env_var(std::string& n, env_ptr p) env_var(std::string& n, env_ptr p)
: name(std::move(n)), parent(std::move(p)) {} : name(std::move(n)), parent(std::move(p)) {}
virtual int get_offset(const std::string& name) const; int get_offset(const std::string& name) const;
bool has_variable(const std::string& name) const;
}; };
struct env_offset { struct env_offset {
@ -27,5 +29,6 @@ struct env_offset {
env_offset(int o, env_ptr p) env_offset(int o, env_ptr p)
: offset(o), parent(std::move(p)) {} : offset(o), parent(std::move(p)) {}
virtual int get_offset(const std::string& name) const; int get_offset(const std::string& name) const;
bool has_variable(const std::string& name) const;
}; };

View File

@ -185,11 +185,26 @@ we see a variable that __isn't__ in the current environment, it must be a functi
Having finished contemplating out method, it's time to define a signature: Having finished contemplating out method, it's time to define a signature:
```C++ ```C++
virtual void compile(const env_ptr env, std::vector<instruction>& into) const; virtual void compile(const env_ptr& env, std::vector<instruction_ptr>& into) const;
``` ```
Ah, but now we have to define "environment". Let's do that: Ah, but now we have to define "environment". Let's do that. Here's our header:
{{< codeblock "C++" "compiler/06/env.hpp" >}} {{< codeblock "C++" "compiler/06/env.hpp" >}}
And here's the source file:
{{< codeblock "C++" "compiler/06/env.cpp" >}}
{{< todo >}}Explain the code drops. {{< /todo >}}
It will also help to move some of the functions on the `binop` enum
into a separate file. The new neader is pretty small:
{{< codeblock "C++" "compiler/06/binop.hpp" >}}
The new source file is not much longer:
{{< codeblock "C++" "compiler/06/binop.cpp" >}}
And now, we begin our implementation. And now, we begin our implementation.