Changed environment to be shared pointer.

This commit is contained in:
yhirose 2015-06-01 16:19:30 -04:00
parent 5b9d6d8a57
commit a4c9cec900
5 changed files with 44 additions and 37 deletions

49
language/interpreter.cc Normal file → Executable file
View 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
View 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
View 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
View 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
View 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