Continue implementation of compilation
This commit is contained in:
parent
64f4abb8d6
commit
d9c151d774
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
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
|
#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
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 ~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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user