diff --git a/language/interpreter.cc b/language/interpreter.cc old mode 100644 new mode 100755 index 58f52fe..22de0cf --- a/language/interpreter.cc +++ b/language/interpreter.cc @@ -7,7 +7,7 @@ using namespace std; struct Eval { - static Value eval(const Ast& ast, Env& env) { + static Value eval(const Ast& ast, shared_ptr& env) { switch (ast.type) { case Statements: return eval_statements(ast, env); case While: return eval_while(ast, env); @@ -32,7 +32,7 @@ struct Eval } private: - static Value eval_statements(const Ast& ast, Env& env) { + static Value eval_statements(const Ast& ast, shared_ptr& env) { if (ast.is_token) { return eval(ast, env); } else if (ast.nodes.empty()) { @@ -46,7 +46,7 @@ private: return eval(**it, env); } - static Value eval_while(const Ast& ast, Env& env) { + static Value eval_while(const Ast& ast, shared_ptr& env) { for (;;) { auto cond = eval(*ast.nodes[0], env); if (!cond.to_bool()) { @@ -57,7 +57,7 @@ private: return Value(); } - static Value eval_if(const Ast& ast, Env& env) { + static Value eval_if(const Ast& ast, shared_ptr& env) { const auto& nodes = ast.nodes; for (auto i = 0u; i < nodes.size(); i += 2) { @@ -74,7 +74,7 @@ private: return Value(); } - static Value eval_function(const Ast& ast, Env& env) { + static Value eval_function(const Ast& ast, shared_ptr& env) { vector params; for (auto node: ast.nodes[0]->nodes) { params.push_back(node->token); @@ -84,12 +84,14 @@ private: auto f = Value::FunctionValue { params, - [=](Env& env) { return eval(*body, env); } + [=](shared_ptr& callEnv) { + return eval(*body, callEnv); + } }; return Value(f); }; - static Value eval_function_call(const Ast& ast, Env& env) { + static Value eval_function_call(const Ast& ast, shared_ptr& env) { const auto& var = ast.nodes[0]->token; const auto& args = ast.nodes[1]->nodes; @@ -97,15 +99,14 @@ private: const auto& fv = f.to_function(); if (fv.params.size() <= args.size()) { - Env callEnv(env); - - callEnv.set("self", f); + auto callEnv = make_shared(env); + callEnv->set("self", f); for (auto i = 0u; i < fv.params.size(); i++) { auto var = fv.params[i]; auto arg = args[i]; auto val = eval(*arg, env); - callEnv.set(var, val); + callEnv->set(var, val); } return fv.eval(callEnv); } @@ -114,7 +115,7 @@ private: throw runtime_error(msg); } - static Value eval_condition(const Ast& ast, Env& env) { + static Value eval_condition(const Ast& ast, shared_ptr& env) { auto lhs = eval(*ast.nodes[0], env); if (ast.nodes.size() > 1) { auto ope = eval(*ast.nodes[1], env).to_string(); @@ -139,7 +140,7 @@ private: return lhs; // Any } - static Value eval_bin_expression(const Ast& ast, Env& env) { + static Value eval_bin_expression(const Ast& ast, shared_ptr& env) { auto ret = eval(*ast.nodes[0], env).to_long(); for (auto i = 1u; i < ast.nodes.size(); i += 2) { auto val = eval(*ast.nodes[i + 1], env).to_long(); @@ -155,27 +156,27 @@ private: return Value(ret); } - static Value eval_assignment(const Ast& ast, Env& env) { + static Value eval_assignment(const Ast& ast, shared_ptr& env) { const auto& var = ast.nodes[0]->token; auto val = eval(*ast.nodes[1], env); - env.set(var, val); + env->set(var, val); return val; }; - static Value eval_identifier(const Ast& ast, Env& env) { + static Value eval_identifier(const Ast& ast, shared_ptr& env) { const auto& var = ast.token; return dereference_identirier(env, var); }; - static Value eval_number(const Ast& ast, Env& env) { + static Value eval_number(const Ast& ast, shared_ptr& env) { return Value(stol(ast.token)); }; - static Value eval_bool(const Ast& ast, Env& env) { + static Value eval_bool(const Ast& ast, shared_ptr& env) { 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& env) { string s; for (auto node: ast.nodes) { const auto& val = eval(*node, env); @@ -184,12 +185,12 @@ private: return Value(s); }; - static Value dereference_identirier(Env& env, const string& var) { - if (!env.has(var)) { + static Value dereference_identirier(shared_ptr& env, const string& var) { + if (!env->has(var)) { string msg = "undefined variable '" + var + "'..."; 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); } -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& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast) { try { - shared_ptr ast; + shared_ptr ast; auto& parser = get_parser(); diff --git a/language/interpreter.hpp b/language/interpreter.hpp old mode 100644 new mode 100755 index e96fe64..ddc670a --- a/language/interpreter.hpp +++ b/language/interpreter.hpp @@ -2,7 +2,7 @@ #include #include -struct Env; +struct Environment; struct Value { @@ -14,7 +14,7 @@ struct Value struct FunctionValue { std::vector params; - std::function eval; + std::function& env)> eval; }; explicit Value() : type(Undefined) {} @@ -163,10 +163,10 @@ private: std::ostream& operator<<(std::ostream& os, const Value& val); -struct Env +struct Environment { - Env() : outer_(nullptr) {} - Env(Env& outer) : outer_(&outer) {} + Environment() = default; + Environment(std::shared_ptr& outer) : outer_(outer) {} bool has(const std::string& s) const { if (dic_.find(s) != dic_.end()) { @@ -187,14 +187,20 @@ struct Env } 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; } void setup_built_in_functions() { auto func_pretty_print = Value::FunctionValue { { "arg" }, - [](Env& env) { - std::cout << env.get("arg").str() << std::endl; + [](std::shared_ptr& env) { + std::cout << env->get("arg").str() << std::endl; return Value(); } }; @@ -202,8 +208,8 @@ struct Env } private: - Env* outer_; + std::shared_ptr outer_; std::map 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& env, const char* expr, size_t len, Value& val, std::string& msg, bool print_ast); diff --git a/language/main.cc b/language/main.cc old mode 100644 new mode 100755 index 376dd81..0bc6818 --- a/language/main.cc +++ b/language/main.cc @@ -45,8 +45,8 @@ int main(int argc, const char** argv) } try { - Env env; - env.setup_built_in_functions(); + auto env = make_shared(); + env->setup_built_in_functions(); for (auto path: path_list) { vector buff; diff --git a/language/repl.cc b/language/repl.cc old mode 100644 new mode 100755 index 688b18a..9baf442 --- a/language/repl.cc +++ b/language/repl.cc @@ -4,7 +4,7 @@ using namespace std; -int repl(Env& env, bool print_ast) +int repl(shared_ptr& env, bool print_ast) { for (;;) { auto line = linenoise::Readline("cul> "); diff --git a/language/repl.hpp b/language/repl.hpp old mode 100644 new mode 100755 index 21dfebd..1ae8005 --- a/language/repl.hpp +++ b/language/repl.hpp @@ -1,5 +1,5 @@ #include "interpreter.hpp" -int repl(Env& env, bool print_ast); +int repl(std::shared_ptr& env, bool print_ast); // vim: et ts=4 sw=4 cin cino={1s ff=unix