mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Changed environment to be shared pointer.
This commit is contained in:
parent
5b9d6d8a57
commit
a4c9cec900
49
language/interpreter.cc
Normal file → Executable file
49
language/interpreter.cc
Normal file → Executable file
@ -7,7 +7,7 @@ using namespace std;
|
|||||||
|
|
||||||
struct Eval
|
struct Eval
|
||||||
{
|
{
|
||||||
static Value eval(const Ast& ast, Env& env) {
|
static Value eval(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
switch (ast.type) {
|
switch (ast.type) {
|
||||||
case Statements: return eval_statements(ast, env);
|
case Statements: return eval_statements(ast, env);
|
||||||
case While: return eval_while(ast, env);
|
case While: return eval_while(ast, env);
|
||||||
@ -32,7 +32,7 @@ struct Eval
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Value eval_statements(const Ast& ast, Env& env) {
|
static Value eval_statements(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
if (ast.is_token) {
|
if (ast.is_token) {
|
||||||
return eval(ast, env);
|
return eval(ast, env);
|
||||||
} else if (ast.nodes.empty()) {
|
} else if (ast.nodes.empty()) {
|
||||||
@ -46,7 +46,7 @@ private:
|
|||||||
return eval(**it, env);
|
return eval(**it, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value eval_while(const Ast& ast, Env& env) {
|
static Value eval_while(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto cond = eval(*ast.nodes[0], env);
|
auto cond = eval(*ast.nodes[0], env);
|
||||||
if (!cond.to_bool()) {
|
if (!cond.to_bool()) {
|
||||||
@ -57,7 +57,7 @@ private:
|
|||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value eval_if(const Ast& ast, Env& env) {
|
static Value eval_if(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
const auto& nodes = ast.nodes;
|
const auto& nodes = ast.nodes;
|
||||||
|
|
||||||
for (auto i = 0u; i < nodes.size(); i += 2) {
|
for (auto i = 0u; i < nodes.size(); i += 2) {
|
||||||
@ -74,7 +74,7 @@ private:
|
|||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value eval_function(const Ast& ast, Env& env) {
|
static Value eval_function(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
vector<string> params;
|
vector<string> params;
|
||||||
for (auto node: ast.nodes[0]->nodes) {
|
for (auto node: ast.nodes[0]->nodes) {
|
||||||
params.push_back(node->token);
|
params.push_back(node->token);
|
||||||
@ -84,12 +84,14 @@ private:
|
|||||||
|
|
||||||
auto f = Value::FunctionValue {
|
auto f = Value::FunctionValue {
|
||||||
params,
|
params,
|
||||||
[=](Env& env) { return eval(*body, env); }
|
[=](shared_ptr<Environment>& callEnv) {
|
||||||
|
return eval(*body, callEnv);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return Value(f);
|
return Value(f);
|
||||||
};
|
};
|
||||||
|
|
||||||
static Value eval_function_call(const Ast& ast, Env& env) {
|
static Value eval_function_call(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
const auto& var = ast.nodes[0]->token;
|
const auto& var = ast.nodes[0]->token;
|
||||||
const auto& args = ast.nodes[1]->nodes;
|
const auto& args = ast.nodes[1]->nodes;
|
||||||
|
|
||||||
@ -97,15 +99,14 @@ private:
|
|||||||
const auto& fv = f.to_function();
|
const auto& fv = f.to_function();
|
||||||
|
|
||||||
if (fv.params.size() <= args.size()) {
|
if (fv.params.size() <= args.size()) {
|
||||||
Env callEnv(env);
|
auto callEnv = make_shared<Environment>(env);
|
||||||
|
callEnv->set("self", f);
|
||||||
callEnv.set("self", f);
|
|
||||||
|
|
||||||
for (auto i = 0u; i < fv.params.size(); i++) {
|
for (auto i = 0u; i < fv.params.size(); i++) {
|
||||||
auto var = fv.params[i];
|
auto var = fv.params[i];
|
||||||
auto arg = args[i];
|
auto arg = args[i];
|
||||||
auto val = eval(*arg, env);
|
auto val = eval(*arg, env);
|
||||||
callEnv.set(var, val);
|
callEnv->set(var, val);
|
||||||
}
|
}
|
||||||
return fv.eval(callEnv);
|
return fv.eval(callEnv);
|
||||||
}
|
}
|
||||||
@ -114,7 +115,7 @@ private:
|
|||||||
throw runtime_error(msg);
|
throw runtime_error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value eval_condition(const Ast& ast, Env& env) {
|
static Value eval_condition(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
auto lhs = eval(*ast.nodes[0], env);
|
auto lhs = eval(*ast.nodes[0], env);
|
||||||
if (ast.nodes.size() > 1) {
|
if (ast.nodes.size() > 1) {
|
||||||
auto ope = eval(*ast.nodes[1], env).to_string();
|
auto ope = eval(*ast.nodes[1], env).to_string();
|
||||||
@ -139,7 +140,7 @@ private:
|
|||||||
return lhs; // Any
|
return lhs; // Any
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value eval_bin_expression(const Ast& ast, Env& env) {
|
static Value eval_bin_expression(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
auto ret = eval(*ast.nodes[0], env).to_long();
|
auto ret = eval(*ast.nodes[0], env).to_long();
|
||||||
for (auto i = 1u; i < ast.nodes.size(); i += 2) {
|
for (auto i = 1u; i < ast.nodes.size(); i += 2) {
|
||||||
auto val = eval(*ast.nodes[i + 1], env).to_long();
|
auto val = eval(*ast.nodes[i + 1], env).to_long();
|
||||||
@ -155,27 +156,27 @@ private:
|
|||||||
return Value(ret);
|
return Value(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Value eval_assignment(const Ast& ast, Env& env) {
|
static Value eval_assignment(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
const auto& var = ast.nodes[0]->token;
|
const auto& var = ast.nodes[0]->token;
|
||||||
auto val = eval(*ast.nodes[1], env);
|
auto val = eval(*ast.nodes[1], env);
|
||||||
env.set(var, val);
|
env->set(var, val);
|
||||||
return val;
|
return val;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Value eval_identifier(const Ast& ast, Env& env) {
|
static Value eval_identifier(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
const auto& var = ast.token;
|
const auto& var = ast.token;
|
||||||
return dereference_identirier(env, var);
|
return dereference_identirier(env, var);
|
||||||
};
|
};
|
||||||
|
|
||||||
static Value eval_number(const Ast& ast, Env& env) {
|
static Value eval_number(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
return Value(stol(ast.token));
|
return Value(stol(ast.token));
|
||||||
};
|
};
|
||||||
|
|
||||||
static Value eval_bool(const Ast& ast, Env& env) {
|
static Value eval_bool(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
return Value(ast.token == "true");
|
return Value(ast.token == "true");
|
||||||
};
|
};
|
||||||
|
|
||||||
static Value eval_interpolated_string(const Ast& ast, Env& env) {
|
static Value eval_interpolated_string(const Ast& ast, shared_ptr<Environment>& env) {
|
||||||
string s;
|
string s;
|
||||||
for (auto node: ast.nodes) {
|
for (auto node: ast.nodes) {
|
||||||
const auto& val = eval(*node, env);
|
const auto& val = eval(*node, env);
|
||||||
@ -184,12 +185,12 @@ private:
|
|||||||
return Value(s);
|
return Value(s);
|
||||||
};
|
};
|
||||||
|
|
||||||
static Value dereference_identirier(Env& env, const string& var) {
|
static Value dereference_identirier(shared_ptr<Environment>& env, const string& var) {
|
||||||
if (!env.has(var)) {
|
if (!env->has(var)) {
|
||||||
string msg = "undefined variable '" + var + "'...";
|
string msg = "undefined variable '" + var + "'...";
|
||||||
throw runtime_error(msg);
|
throw runtime_error(msg);
|
||||||
}
|
}
|
||||||
return env.get(var);
|
return env->get(var);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -198,10 +199,10 @@ std::ostream& operator<<(std::ostream& os, const Value& val)
|
|||||||
return val.out(os);
|
return val.out(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool run(const string& path, Env& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast)
|
bool run(const string& path, shared_ptr<Environment>& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
shared_ptr<Ast> ast;
|
shared_ptr<Ast> ast;
|
||||||
|
|
||||||
auto& parser = get_parser();
|
auto& parser = get_parser();
|
||||||
|
|
||||||
|
24
language/interpreter.hpp
Normal file → Executable file
24
language/interpreter.hpp
Normal file → Executable file
@ -2,7 +2,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <peglib.h>
|
#include <peglib.h>
|
||||||
|
|
||||||
struct Env;
|
struct Environment;
|
||||||
|
|
||||||
struct Value
|
struct Value
|
||||||
{
|
{
|
||||||
@ -14,7 +14,7 @@ struct Value
|
|||||||
|
|
||||||
struct FunctionValue {
|
struct FunctionValue {
|
||||||
std::vector<std::string> params;
|
std::vector<std::string> params;
|
||||||
std::function<Value (Env& env)> eval;
|
std::function<Value (std::shared_ptr<Environment>& env)> eval;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Value() : type(Undefined) {}
|
explicit Value() : type(Undefined) {}
|
||||||
@ -163,10 +163,10 @@ private:
|
|||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const Value& val);
|
std::ostream& operator<<(std::ostream& os, const Value& val);
|
||||||
|
|
||||||
struct Env
|
struct Environment
|
||||||
{
|
{
|
||||||
Env() : outer_(nullptr) {}
|
Environment() = default;
|
||||||
Env(Env& outer) : outer_(&outer) {}
|
Environment(std::shared_ptr<Environment>& outer) : outer_(outer) {}
|
||||||
|
|
||||||
bool has(const std::string& s) const {
|
bool has(const std::string& s) const {
|
||||||
if (dic_.find(s) != dic_.end()) {
|
if (dic_.find(s) != dic_.end()) {
|
||||||
@ -187,14 +187,20 @@ struct Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set(const std::string& s, const Value& val) {
|
void set(const std::string& s, const Value& val) {
|
||||||
|
if (dic_.find(s) != dic_.end()) {
|
||||||
|
dic_[s] = val;
|
||||||
|
}
|
||||||
|
if (outer_ && outer_->has(s)) {
|
||||||
|
return outer_->set(s, val);
|
||||||
|
}
|
||||||
dic_[s] = val;
|
dic_[s] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_built_in_functions() {
|
void setup_built_in_functions() {
|
||||||
auto func_pretty_print = Value::FunctionValue {
|
auto func_pretty_print = Value::FunctionValue {
|
||||||
{ "arg" },
|
{ "arg" },
|
||||||
[](Env& env) {
|
[](std::shared_ptr<Environment>& env) {
|
||||||
std::cout << env.get("arg").str() << std::endl;
|
std::cout << env->get("arg").str() << std::endl;
|
||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -202,8 +208,8 @@ struct Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Env* outer_;
|
std::shared_ptr<Environment> outer_;
|
||||||
std::map<std::string, Value> dic_;
|
std::map<std::string, Value> dic_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool run(const std::string& path, Env& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast);
|
bool run(const std::string& path, std::shared_ptr<Environment>& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast);
|
||||||
|
4
language/main.cc
Normal file → Executable file
4
language/main.cc
Normal file → Executable file
@ -45,8 +45,8 @@ int main(int argc, const char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Env env;
|
auto env = make_shared<Environment>();
|
||||||
env.setup_built_in_functions();
|
env->setup_built_in_functions();
|
||||||
|
|
||||||
for (auto path: path_list) {
|
for (auto path: path_list) {
|
||||||
vector<char> buff;
|
vector<char> buff;
|
||||||
|
2
language/repl.cc
Normal file → Executable file
2
language/repl.cc
Normal file → Executable file
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int repl(Env& env, bool print_ast)
|
int repl(shared_ptr<Environment>& env, bool print_ast)
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto line = linenoise::Readline("cul> ");
|
auto line = linenoise::Readline("cul> ");
|
||||||
|
2
language/repl.hpp
Normal file → Executable file
2
language/repl.hpp
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
#include "interpreter.hpp"
|
#include "interpreter.hpp"
|
||||||
|
|
||||||
int repl(Env& env, bool print_ast);
|
int repl(std::shared_ptr<Environment>& env, bool print_ast);
|
||||||
|
|
||||||
// vim: et ts=4 sw=4 cin cino={1s ff=unix
|
// vim: et ts=4 sw=4 cin cino={1s ff=unix
|
||||||
|
Loading…
Reference in New Issue
Block a user