Continue implementation of compilation
This commit is contained in:
parent
64f4abb8d6
commit
d9c151d774
|
@ -18,6 +18,7 @@ add_executable(compiler
|
|||
env.cpp env.hpp
|
||||
type.cpp type.hpp
|
||||
error.cpp error.hpp
|
||||
binop.cpp binop.hpp
|
||||
${BISON_parser_OUTPUTS}
|
||||
${FLEX_scanner_OUTPUTS}
|
||||
main.cpp
|
||||
|
|
|
@ -2,16 +2,6 @@
|
|||
#include <ostream>
|
||||
#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) {
|
||||
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"));
|
||||
}
|
||||
|
||||
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 {
|
||||
print_indent(indent, to);
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
print_indent(indent, to);
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
print_indent(indent, to);
|
||||
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;
|
||||
}
|
||||
|
||||
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 {
|
||||
print_indent(indent, to);
|
||||
to << "APP:" << std::endl;
|
||||
|
@ -81,6 +94,12 @@ type_ptr ast_app::typecheck(type_mgr& mgr, const type_env& env) const {
|
|||
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 {
|
||||
print_indent(indent, to);
|
||||
to << "CASE: " << std::endl;
|
||||
|
@ -111,6 +130,10 @@ type_ptr ast_case::typecheck(type_mgr& mgr, const type_env& env) const {
|
|||
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 {
|
||||
to << var;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ struct ast {
|
|||
|
||||
virtual void print(int indent, std::ostream& to) const = 0;
|
||||
virtual type_ptr typecheck(type_mgr& mgr, const type_env& env) const = 0;
|
||||
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 = 0;
|
||||
};
|
||||
|
||||
using ast_ptr = std::unique_ptr<ast>;
|
||||
|
@ -64,6 +64,7 @@ struct ast_int : public ast {
|
|||
|
||||
void print(int indent, std::ostream& to) 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 {
|
||||
|
@ -74,6 +75,7 @@ struct ast_lid : public ast {
|
|||
|
||||
void print(int indent, std::ostream& to) 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 {
|
||||
|
@ -84,6 +86,7 @@ struct ast_uid : public ast {
|
|||
|
||||
void print(int indent, std::ostream& to) 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 {
|
||||
|
@ -96,6 +99,7 @@ struct ast_binop : public ast {
|
|||
|
||||
void print(int indent, std::ostream& to) 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 {
|
||||
|
@ -107,6 +111,7 @@ struct ast_app : public ast {
|
|||
|
||||
void print(int indent, std::ostream& to) 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 {
|
||||
|
@ -118,6 +123,7 @@ struct ast_case : public ast {
|
|||
|
||||
void print(int indent, std::ostream& to) 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 {
|
||||
|
|
21
code/compiler/06/binop.cpp
Normal file
21
code/compiler/06/binop.cpp
Normal 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 "??";
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
|
||||
enum binop {
|
||||
PLUS,
|
||||
|
@ -7,3 +8,5 @@ enum binop {
|
|||
DIVIDE
|
||||
};
|
||||
|
||||
std::string op_name(binop op);
|
||||
std::string op_action(binop op);
|
||||
|
|
23
code/compiler/06/env.cpp
Normal file
23
code/compiler/06/env.cpp
Normal 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;
|
||||
}
|
|
@ -6,6 +6,7 @@ struct env {
|
|||
virtual ~env() = default;
|
||||
|
||||
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>;
|
||||
|
@ -17,7 +18,8 @@ struct env_var {
|
|||
env_var(std::string& n, env_ptr 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 {
|
||||
|
@ -27,5 +29,6 @@ struct env_offset {
|
|||
env_offset(int o, env_ptr 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;
|
||||
};
|
||||
|
|
|
@ -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:
|
||||
```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" >}}
|
||||
|
||||
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.
|
||||
|
|
Loading…
Reference in New Issue
Block a user