diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index e79a34d..4f2a83b 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -15,34 +15,31 @@ namespace chaiscript * Helper function that will set up the scope around a function call, including handling the named function parameters */ template - const Boxed_Value eval_function (Eval_System &ss, TokenPtr node, const std::vector ¶m_names, const std::vector &vals) { + const Boxed_Value eval_function (Eval_System &ss, const TokenPtr &node, const std::vector ¶m_names, const std::vector &vals) { ss.new_scope(); for (unsigned int i = 0; i < param_names.size(); ++i) { ss.add_object(param_names[i], vals[i]); } - Boxed_Value retval; - try { - retval = eval_token(ss, node); + Boxed_Value retval(eval_token(ss, node)); ss.pop_scope(); + return retval; } catch (const Return_Value &rv) { - retval = rv.retval; ss.pop_scope(); + return rv.retval; } catch (...) { ss.pop_scope(); throw; } - - return retval; } /** * Evaluates the top-level file node */ template - Boxed_Value eval_file(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_file(Eval_System &ss, const TokenPtr &node) { Boxed_Value retval; unsigned int i; for (i = 0; i < node->children.size(); ++i) { @@ -55,7 +52,7 @@ namespace chaiscript * Evaluates a variable or function name identifier */ template - Boxed_Value eval_id(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_id(Eval_System &ss, const TokenPtr &node) { if (node->text == "true") { return Boxed_Value(true); @@ -77,7 +74,7 @@ namespace chaiscript * Evaluates a floating point number */ template - Boxed_Value eval_float(Eval_System &, TokenPtr node) { + Boxed_Value eval_float(Eval_System &, const TokenPtr &node) { return Boxed_Value(double(atof(node->text.c_str()))); } @@ -85,7 +82,7 @@ namespace chaiscript * Evaluates an integer */ template - Boxed_Value eval_int(Eval_System &, TokenPtr node) { + Boxed_Value eval_int(Eval_System &, const TokenPtr &node) { return Boxed_Value(atoi(node->text.c_str())); } @@ -93,7 +90,7 @@ namespace chaiscript * Evaluates a quoted string */ template - Boxed_Value eval_quoted_string(Eval_System &, TokenPtr node) { + Boxed_Value eval_quoted_string(Eval_System &, const TokenPtr &node) { return Boxed_Value(node->text); } @@ -101,7 +98,7 @@ namespace chaiscript * Evaluates a char group */ template - Boxed_Value eval_single_quoted_string(Eval_System &, TokenPtr node) { + Boxed_Value eval_single_quoted_string(Eval_System &, const TokenPtr &node) { if (node->text.size() == 1) { return Boxed_Value(char(node->text[0])); } @@ -114,10 +111,9 @@ namespace chaiscript * Evaluates a string of equations in reverse order so that the right-most side has precedence */ template - Boxed_Value eval_equation(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_equation(Eval_System &ss, const TokenPtr &node) { unsigned int i; - retval = eval_token(ss, node->children.back()); + Boxed_Value retval = eval_token(ss, node->children.back()); if (node->children.size() > 1) { for (i = node->children.size()-3; ((int)i) >= 0; i -= 2) { if (node->children[i+1]->text == "=") { @@ -170,7 +166,7 @@ namespace chaiscript * Evaluates a variable declaration */ template - Boxed_Value eval_var_decl(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_var_decl(Eval_System &ss, const TokenPtr &node) { try { ss.add_object(node->children[0]->text, Boxed_Value()); } @@ -184,11 +180,10 @@ namespace chaiscript * Evaluates binary boolean operators. Respects short-circuiting rules. */ template - Boxed_Value eval_expression(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_expression(Eval_System &ss, const TokenPtr &node) { unsigned int i; - retval = eval_token(ss, node->children[0]); + Boxed_Value retval = eval_token(ss, node->children[0]); if (node->children.size() > 1) { for (i = 1; i < node->children.size(); i += 2) { bool lhs; @@ -223,11 +218,10 @@ namespace chaiscript * Evaluates comparison, additions, and multiplications and their relatives */ template - Boxed_Value eval_comp_add_mul(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_comp_add_mul(Eval_System &ss, const TokenPtr &node) { unsigned int i; - retval = eval_token(ss, node->children[0]); + Boxed_Value retval = eval_token(ss, node->children[0]); if (node->children.size() > 1) { for (i = 1; i < node->children.size(); i += 2) { Param_List_Builder plb; @@ -250,11 +244,10 @@ namespace chaiscript * Evaluates an array lookup */ template - Boxed_Value eval_array_call(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_array_call(Eval_System &ss, const TokenPtr &node) { unsigned int i; - retval = eval_token(ss, node->children[0]); + Boxed_Value retval = eval_token(ss, node->children[0]); for (i = 1; i < node->children.size(); ++i) { Param_List_Builder plb; plb << retval; @@ -277,10 +270,8 @@ namespace chaiscript * Evaluates a unary negation */ template - Boxed_Value eval_negate(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; - - retval = eval_token(ss, node->children[0]); + Boxed_Value eval_negate(Eval_System &ss, const TokenPtr &node) { + Boxed_Value retval = eval_token(ss, node->children[0]); Param_List_Builder plb; plb << retval; plb << Boxed_Value(-1.0); @@ -297,30 +288,22 @@ namespace chaiscript * Evaluates a unary boolean not */ template - Boxed_Value eval_not(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; - - bool cond; + Boxed_Value eval_not(Eval_System &ss, const TokenPtr &node) { try { - retval = eval_token(ss, node->children[0]); - cond = boxed_cast(retval); + return Boxed_Value(!boxed_cast(eval_token(ss, node->children[0]))); } catch (const bad_boxed_cast &) { throw Eval_Error("Boolean not('!') condition not boolean", node->children[0]); } - return Boxed_Value(!cond); } /** * Evaluates any unary prefix */ template - Boxed_Value eval_prefix(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; - - retval = eval_token(ss, node->children[1]); + Boxed_Value eval_prefix(Eval_System &ss, const TokenPtr &node) { Param_List_Builder plb; - plb << retval; + plb << eval_token(ss, node->children[1]); try { return ss.call_function(node->children[0]->text, plb); @@ -334,12 +317,11 @@ namespace chaiscript * Evaluates (and generates) an inline array initialization */ template - Boxed_Value eval_inline_array(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_inline_array(Eval_System &ss, const TokenPtr &node) { unsigned int i; try { - retval = ss.call_function("Vector", Param_List_Builder()); + Boxed_Value retval = ss.call_function("Vector", Param_List_Builder()); if (node->children.size() > 0) { for (i = 0; i < node->children[0]->children.size(); ++i) { try { @@ -351,19 +333,20 @@ namespace chaiscript } } } + + return retval; } catch (const dispatch_error &) { throw Eval_Error("Can not find appropriate 'Vector()'", node); } - return retval; } /** * Evaluates (and generates) an inline range initialization */ template - Boxed_Value eval_inline_range(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_inline_range(Eval_System &ss, const TokenPtr &node) { try { return ss.call_function("generate_range", Param_List_Builder() << eval_token(ss, node->children[0]->children[0]->children[0]) @@ -378,12 +361,11 @@ namespace chaiscript * Evaluates (and generates) an inline map initialization */ template - Boxed_Value eval_inline_map(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_inline_map(Eval_System &ss, const TokenPtr &node) { unsigned int i; try { - retval = ss.call_function("Map", Param_List_Builder()); + Boxed_Value retval = ss.call_function("Map", Param_List_Builder()); for (i = 0; i < node->children[0]->children.size(); ++i) { try { Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]); @@ -394,20 +376,18 @@ namespace chaiscript throw Eval_Error("Can not find appropriate '=' for map init", node->children[0]->children[i]); } } + return retval; } catch (const dispatch_error &) { throw Eval_Error("Can not find appropriate 'Map()'", node); } - - return retval; } /** * Evaluates a function call, starting with its arguments. Handles resetting the scope to the previous one after the call. */ template - Boxed_Value eval_fun_call(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_fun_call(Eval_System &ss, const TokenPtr &node) { Param_List_Builder plb; Dispatch_Engine::Stack prev_stack = ss.get_stack(); Dispatch_Engine::Stack new_stack = ss.new_stack(); @@ -418,41 +398,41 @@ namespace chaiscript plb << eval_token(ss, node->children[1]->children[i]); } } - Boxed_Value fn; + try { - fn = eval_token(ss, node->children[0]); + Boxed_Value fn = eval_token(ss, node->children[0]); + + try { + ss.set_stack(new_stack); + Boxed_Value retval = (*boxed_cast(fn))(plb); + ss.set_stack(prev_stack); + return retval; + } + catch(const dispatch_error &e){ + ss.set_stack(prev_stack); + throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]); + } + catch(Return_Value &rv) { + ss.set_stack(prev_stack); + return rv.retval; + } + catch(...) { + ss.set_stack(prev_stack); + throw; + } } catch(Eval_Error &ee) { ss.set_stack(prev_stack); throw Eval_Error(ee.reason, node->children[0]); } - try { - ss.set_stack(new_stack); - retval = (*boxed_cast(fn))(plb); - ss.set_stack(prev_stack); - } - catch(const dispatch_error &e){ - ss.set_stack(prev_stack); - throw Eval_Error(std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]); - } - catch(Return_Value &rv) { - ss.set_stack(prev_stack); - retval = rv.retval; - } - catch(...) { - ss.set_stack(prev_stack); - throw; - } - return retval; } /** * Evaluates a method/attributes invocation */ template - Boxed_Value eval_dot_access(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_dot_access(Eval_System &ss, const TokenPtr &node) { std::vector > fn; Dispatch_Engine::Stack prev_stack = ss.get_stack(); Dispatch_Engine::Stack new_stack = ss.new_stack(); @@ -460,7 +440,7 @@ namespace chaiscript //todo: Please extract a single way of doing function calls between this and eval_fun_call - retval = eval_token(ss, node->children[0]); + Boxed_Value retval = eval_token(ss, node->children[0]); if (node->children.size() > 1) { for (i = 1; i < node->children.size(); ++i) { Param_List_Builder plb; @@ -517,11 +497,10 @@ namespace chaiscript * Evaluates an if/elseif/else block */ template - Boxed_Value eval_if(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_if(Eval_System &ss, const TokenPtr &node) { unsigned int i; - retval = eval_token(ss, node->children[0]); + Boxed_Value retval = eval_token(ss, node->children[0]); bool cond; try { cond = boxed_cast(retval); @@ -564,7 +543,7 @@ namespace chaiscript * Evaluates a while block */ template - Boxed_Value eval_while(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_while(Eval_System &ss, const TokenPtr &node) { bool cond; ss.new_scope(); @@ -599,7 +578,7 @@ namespace chaiscript * Evaluates a for block, including the for's conditions, from left to right */ template - Boxed_Value eval_for(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_for(Eval_System &ss, const TokenPtr &node) { bool cond; ss.new_scope(); @@ -646,8 +625,7 @@ namespace chaiscript * Evaluates a function definition */ template - Boxed_Value eval_def(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_def(Eval_System &ss, const TokenPtr &node) { unsigned int i; std::vector param_names; @@ -693,15 +671,14 @@ namespace chaiscript catch (reserved_word_error &rwe) { throw Eval_Error("Reserved word used as function name '" + function_name + "'", node); } - return retval; + return Boxed_Value(); } /** * Evaluates a lambda (anonymous function) */ template - Boxed_Value eval_lambda(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_lambda(Eval_System &ss, const TokenPtr &node) { unsigned int i; std::vector param_names; @@ -728,7 +705,7 @@ namespace chaiscript * Evaluates a scoped block. Handles resetting the scope after the block has completed. */ template - Boxed_Value eval_block(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_block(Eval_System &ss, const TokenPtr &node) { Boxed_Value retval; unsigned int i; @@ -756,22 +733,20 @@ namespace chaiscript * Evaluates a return statement */ template - Boxed_Value eval_return(Eval_System &ss, TokenPtr node) { - Boxed_Value retval; + Boxed_Value eval_return(Eval_System &ss, const TokenPtr &node) { if (node->children.size() > 0) { - retval = eval_token(ss, node->children[0]); + throw Return_Value(eval_token(ss, node->children[0]), node); } else { - retval = Boxed_Value(); + throw Return_Value(Boxed_Value(), node); } - throw Return_Value(retval, node); } /** * Evaluates a break statement */ template - Boxed_Value eval_break(Eval_System &, TokenPtr node) { + Boxed_Value eval_break(Eval_System &, const TokenPtr &node) { throw Break_Loop(node); } @@ -779,7 +754,7 @@ namespace chaiscript * Top-level evaluation dispatch for all AST node types */ template - Boxed_Value eval_token(Eval_System &ss, TokenPtr node) { + Boxed_Value eval_token(Eval_System &ss, const TokenPtr &node) { switch (node->identifier) { case (Token_Type::File) : return eval_file(ss, node);