|
|
@ -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,7 +199,7 @@ 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; |
|
|
|