diff --git a/chaiscript/chaiscript_engine.hpp b/chaiscript/chaiscript_engine.hpp index 30f5fea..7772d00 100644 --- a/chaiscript/chaiscript_engine.hpp +++ b/chaiscript/chaiscript_engine.hpp @@ -23,10 +23,16 @@ namespace chaiscript } + /** + * Returns the current evaluation engine + */ Eval_Engine &get_eval_engine() { return engine; } + /** + * Prints the contents of an AST node, including its children, recursively + */ void debug_print(TokenPtr t, std::string prepend = "") { std::cout << prepend << "(" << token_type_to_string(t->identifier) << ") " << t->text << " : " << t->start.line << ", " << t->start.column << std::endl; for (unsigned int j = 0; j < t->children.size(); ++j) { @@ -34,6 +40,9 @@ namespace chaiscript } } + /** + * Evaluates the given boxed string, used during eval() inside of a script + */ const dispatchkit::Boxed_Value eval(const std::vector &vals) { std::string val; try { @@ -48,6 +57,9 @@ namespace chaiscript return evaluate_string(val); } + /** + * Helper function for loading a file + */ std::string load_file(const char *filename) { std::ifstream infile (filename, std::ios::in | std::ios::ate); @@ -67,6 +79,9 @@ namespace chaiscript return ret_val; } + /** + * Builds all the requirements for ChaiScript, including its evaluator and a run of its prelude. + */ void build_eval_system() { dispatchkit::Bootstrap::bootstrap(engine); dispatchkit::bootstrap_vector >(engine, "Vector"); @@ -80,6 +95,9 @@ namespace chaiscript evaluate_string(chaiscript_prelude); } + /** + * Evaluates the given string in by parsing it and running the results through the evaluator + */ dispatchkit::Boxed_Value evaluate_string(const std::string &input, const char *filename = "__EVAL__") { //debug_print(tokens); dispatchkit::Boxed_Value value; @@ -112,6 +130,9 @@ namespace chaiscript return value; } + /** + * Loads the file specified by filename, evaluates it, and returns the result + */ dispatchkit::Boxed_Value evaluate_file(const char *filename) { return evaluate_string(load_file(filename), filename); } diff --git a/chaiscript/chaiscript_eval.hpp b/chaiscript/chaiscript_eval.hpp index eca4051..4d2ad9a 100644 --- a/chaiscript/chaiscript_eval.hpp +++ b/chaiscript/chaiscript_eval.hpp @@ -34,288 +34,393 @@ namespace chaiscript } template - dispatchkit::Boxed_Value eval_token(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value eval_file(Eval_System &ss, TokenPtr node) { dispatchkit::Boxed_Value retval; - unsigned int i, j; + unsigned int i; + for (i = 0; i < node->children.size(); ++i) { + retval = eval_token(ss, node->children[i]); + } + return retval; + } - switch (node->identifier) { - case (Token_Type::File) : - for (i = 0; i < node->children.size(); ++i) { - retval = eval_token(ss, node->children[i]); - } - break; - case (Token_Type::Id) : - if (node->text == "true") { - retval = dispatchkit::Boxed_Value(true); - } - else if (node->text == "false") { - retval = dispatchkit::Boxed_Value(false); - } - else { + template + dispatchkit::Boxed_Value eval_id(Eval_System &ss, TokenPtr node) { + + if (node->text == "true") { + return dispatchkit::Boxed_Value(true); + } + else if (node->text == "false") { + return dispatchkit::Boxed_Value(false); + } + else { + try { + return ss.get_object(node->text); + } + catch (std::exception &e) { + throw EvalError("Can not find object: " + node->text, node); + } + } + } + + template + dispatchkit::Boxed_Value eval_float(Eval_System &ss, TokenPtr node) { + return dispatchkit::Boxed_Value(double(atof(node->text.c_str()))); + } + + template + dispatchkit::Boxed_Value eval_int(Eval_System &ss, TokenPtr node) { + return dispatchkit::Boxed_Value(atoi(node->text.c_str())); + } + + template + dispatchkit::Boxed_Value eval_quoted_string(Eval_System &ss, TokenPtr node) { + return dispatchkit::Boxed_Value(node->text); + } + + template + dispatchkit::Boxed_Value eval_single_quoted_string(Eval_System &ss, TokenPtr node) { + return dispatchkit::Boxed_Value(node->text); + } + + template + dispatchkit::Boxed_Value eval_equation(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + 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 == "=") { + dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]); try { - retval = ss.get_object(node->text); - } - catch (std::exception &e) { - throw EvalError("Can not find object: " + node->text, node); - } - } - break; - case (Token_Type::Float) : - retval = dispatchkit::Boxed_Value(double(atof(node->text.c_str()))); - break; - case (Token_Type::Int) : - retval = dispatchkit::Boxed_Value(atoi(node->text.c_str())); - break; - case (Token_Type::Quoted_String) : - retval = dispatchkit::Boxed_Value(node->text); - break; - case (Token_Type::Single_Quoted_String) : - retval = dispatchkit::Boxed_Value(node->text); - break; - case (Token_Type::Equation) : - 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 == "=") { - dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]); - try { - if (lhs.is_unknown()) - { - retval = dispatch(ss.get_function("clone"), dispatchkit::Param_List_Builder() << retval); - } - dispatchkit::Param_List_Builder plb; - plb << lhs; - plb << retval; - try { - retval = dispatch(ss.get_function(node->children[i+1]->text), plb); - } - catch(const dispatchkit::dispatch_error &e){ - throw EvalError("Mismatched types in equation", node->children[i+1]); - } - } - catch(const dispatchkit::dispatch_error &e){ - throw EvalError("Can not clone right hand side of equation", node->children[i+1]); - } + if (lhs.is_unknown()) + { + retval = dispatch(ss.get_function("clone"), dispatchkit::Param_List_Builder() << retval); } - else if (node->children[i+1]->text == ":=") { - dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]); - if (lhs.is_unknown() || dispatchkit::Bootstrap::type_match(lhs, retval)) { - lhs.assign(retval); - } - else { - throw EvalError("Mismatched types in equation", node->children[i+1]); - } - } - else { - dispatchkit::Param_List_Builder plb; - plb << eval_token(ss, node->children[i]); - plb << retval; - try { - retval = dispatch(ss.get_function(node->children[i+1]->text), plb); - } - catch(const dispatchkit::dispatch_error &e){ - throw EvalError("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]); - } - } - } - } - break; - case (Token_Type::Var_Decl): { - ss.add_object(node->children[0]->text, dispatchkit::Boxed_Value()); - retval = ss.get_object(node->children[0]->text); - } - break; - case (Token_Type::Expression) : { - retval = eval_token(ss, node->children[0]); - if (node->children.size() > 1) { - for (i = 1; i < node->children.size(); i += 2) { - bool lhs; - try { - lhs = dispatchkit::boxed_cast(retval); - } - catch (std::exception &e) { - throw EvalError("Condition not boolean", node); - } - if (node->children[i]->text == "&&") { - if (lhs) { - retval = eval_token(ss, node->children[i+1]); - } - else { - retval = dispatchkit::Boxed_Value(false); - } - } - else if (node->children[i]->text == "||") { - if (lhs) { - retval = dispatchkit::Boxed_Value(true); - } - else { - retval = eval_token(ss, node->children[i+1]); - } - } - } - } - } - break; - case (Token_Type::Comparison) : - case (Token_Type::Additive) : - case (Token_Type::Multiplicative) : { - retval = eval_token(ss, node->children[0]); - if (node->children.size() > 1) { - for (i = 1; i < node->children.size(); i += 2) { dispatchkit::Param_List_Builder plb; + plb << lhs; plb << retval; - plb << eval_token(ss, node->children[i + 1]); - try { - retval = dispatch(ss.get_function(node->children[i]->text), plb); + retval = dispatch(ss.get_function(node->children[i+1]->text), plb); } catch(const dispatchkit::dispatch_error &e){ - throw EvalError("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]); + throw EvalError("Mismatched types in equation", node->children[i+1]); } } - } - } - break; - case (Token_Type::Array_Call) : { - retval = eval_token(ss, node->children[0]); - for (i = 1; i < node->children.size(); ++i) { - dispatchkit::Param_List_Builder plb; - plb << retval; - plb << eval_token(ss, node->children[i]); - try { - retval = dispatch(ss.get_function("[]"), plb); - } - catch(std::out_of_range &oor) { - throw EvalError("Out of bounds exception", node); - } catch(const dispatchkit::dispatch_error &e){ - throw EvalError("Can not find appropriate array lookup '[]' " + node->children[i]->text, node->children[i]); + throw EvalError("Can not clone right hand side of equation", node->children[i+1]); + } + } + else if (node->children[i+1]->text == ":=") { + dispatchkit::Boxed_Value lhs = eval_token(ss, node->children[i]); + if (lhs.is_unknown() || dispatchkit::Bootstrap::type_match(lhs, retval)) { + lhs.assign(retval); + } + else { + throw EvalError("Mismatched types in equation", node->children[i+1]); + } + } + else { + dispatchkit::Param_List_Builder plb; + plb << eval_token(ss, node->children[i]); + plb << retval; + try { + retval = dispatch(ss.get_function(node->children[i+1]->text), plb); + } + catch(const dispatchkit::dispatch_error &e){ + throw EvalError("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]); } } } - break; - case (Token_Type::Negate) : { - retval = eval_token(ss, node->children[0]); + } + return retval; + } + + template + dispatchkit::Boxed_Value eval_var_decl(Eval_System &ss, TokenPtr node) { + ss.add_object(node->children[0]->text, dispatchkit::Boxed_Value()); + return ss.get_object(node->children[0]->text); + } + + template + dispatchkit::Boxed_Value eval_expression(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + retval = eval_token(ss, node->children[0]); + if (node->children.size() > 1) { + for (i = 1; i < node->children.size(); i += 2) { + bool lhs; + try { + lhs = dispatchkit::boxed_cast(retval); + } + catch (std::exception &e) { + throw EvalError("Condition not boolean", node); + } + if (node->children[i]->text == "&&") { + if (lhs) { + retval = eval_token(ss, node->children[i+1]); + } + else { + retval = dispatchkit::Boxed_Value(false); + } + } + else if (node->children[i]->text == "||") { + if (lhs) { + retval = dispatchkit::Boxed_Value(true); + } + else { + retval = eval_token(ss, node->children[i+1]); + } + } + } + } + return retval; + } + + template + dispatchkit::Boxed_Value eval_comp_add_mul(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + retval = eval_token(ss, node->children[0]); + if (node->children.size() > 1) { + for (i = 1; i < node->children.size(); i += 2) { dispatchkit::Param_List_Builder plb; plb << retval; - plb << dispatchkit::Boxed_Value(-1); + plb << eval_token(ss, node->children[i + 1]); try { - retval = dispatch(ss.get_function("*"), plb); + retval = dispatch(ss.get_function(node->children[i]->text), plb); } - catch(std::exception &e){ - throw EvalError("Can not find appropriate negation", node->children[0]); + catch(const dispatchkit::dispatch_error &e){ + throw EvalError("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]); } } - break; - case (Token_Type::Not) : { - bool cond; + } + + return retval; + } + + template + dispatchkit::Boxed_Value eval_array_call(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + retval = eval_token(ss, node->children[0]); + for (i = 1; i < node->children.size(); ++i) { + dispatchkit::Param_List_Builder plb; + plb << retval; + plb << eval_token(ss, node->children[i]); + try { + retval = dispatch(ss.get_function("[]"), plb); + } + catch(std::out_of_range &oor) { + throw EvalError("Out of bounds exception", node); + } + catch(const dispatchkit::dispatch_error &e){ + throw EvalError("Can not find appropriate array lookup '[]' " + node->children[i]->text, node->children[i]); + } + } + + return retval; + } + + template + dispatchkit::Boxed_Value eval_negate(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + + retval = eval_token(ss, node->children[0]); + dispatchkit::Param_List_Builder plb; + plb << retval; + plb << dispatchkit::Boxed_Value(-1); + + try { + return dispatch(ss.get_function("*"), plb); + } + catch(std::exception &e){ + throw EvalError("Can not find appropriate negation", node->children[0]); + } + } + + template + dispatchkit::Boxed_Value eval_not(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + + bool cond; + try { + retval = eval_token(ss, node->children[0]); + cond = dispatchkit::boxed_cast(retval); + } + catch (std::exception) { + throw EvalError("Boolean not('!') condition not boolean", node->children[0]); + } + return dispatchkit::Boxed_Value(!cond); + } + + template + dispatchkit::Boxed_Value eval_prefix(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + + retval = eval_token(ss, node->children[1]); + dispatchkit::Param_List_Builder plb; + plb << retval; + + try { + return dispatch(ss.get_function(node->children[0]->text), plb); + } + catch(std::exception &e){ + throw EvalError("Can not find appropriate prefix", node->children[0]); + } + } + + template + dispatchkit::Boxed_Value eval_inline_array(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + try { + retval = dispatch(ss.get_function("Vector"), dispatchkit::Param_List_Builder()); + if (node->children.size() > 0) { + for (i = 0; i < node->children[0]->children.size(); ++i) { + try { + dispatchkit::Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]); + dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << tmp); + } + catch (const dispatchkit::dispatch_error &inner_e) { + throw EvalError("Can not find appropriate 'push_back'", node->children[0]->children[i]); + } + } + } + } + catch (const dispatchkit::dispatch_error &e) { + throw EvalError("Can not find appropriate 'Vector()'", node); + } + + return retval; + } + + template + dispatchkit::Boxed_Value eval_inline_range(Eval_System &ss, TokenPtr node) { + try { + return dispatch(ss.get_function("generate_range"), dispatchkit::Param_List_Builder() + << eval_token(ss, node->children[0]->children[0]->children[0]) + << eval_token(ss, node->children[0]->children[0]->children[1])); + } + catch (const dispatchkit::dispatch_error &e) { + throw EvalError("Unable to generate range vector", node); + } + } + + template + dispatchkit::Boxed_Value eval_inline_map(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + try { + retval = dispatch(ss.get_function("Map"), dispatchkit::Param_List_Builder()); + for (i = 0; i < node->children[0]->children.size(); ++i) { try { - retval = eval_token(ss, node->children[0]); - cond = dispatchkit::boxed_cast(retval); + dispatchkit::Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]); + dispatchkit::Boxed_Value slot = dispatch(ss.get_function("[]"), dispatchkit::Param_List_Builder() << retval << key); + dispatch(ss.get_function("="), dispatchkit::Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1])); } - catch (std::exception) { - throw EvalError("Boolean not('!') condition not boolean", node->children[0]); + catch (const dispatchkit::dispatch_error &inner_e) { + throw EvalError("Can not find appropriate '=' for map init", node->children[0]->children[i]); } - retval = dispatchkit::Boxed_Value(!cond); } - break; - case (Token_Type::Prefix) : { - retval = eval_token(ss, node->children[1]); + } + catch (const dispatchkit::dispatch_error &e) { + throw EvalError("Can not find appropriate 'Map()'", node); + } + + return retval; + } + + template + dispatchkit::Boxed_Value eval_fun_call(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + dispatchkit::Param_List_Builder plb; + dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack(); + dispatchkit::Dispatch_Engine::Stack new_stack; + unsigned int i; + + new_stack.push_back(dispatchkit::Dispatch_Engine::Scope()); + + if ((node->children.size() > 1) && (node->children[1]->identifier == Token_Type::Arg_List)) { + for (i = 0; i < node->children[1]->children.size(); ++i) { + plb << eval_token(ss, node->children[1]->children[i]); + } + } + dispatchkit::Boxed_Value fn; + try { + fn = eval_token(ss, node->children[0]); + } + catch(EvalError &ee) { + ss.set_stack(prev_stack); + throw EvalError(ee.reason, node->children[0]); + } + try { + ss.set_stack(new_stack); + retval = (*dispatchkit::boxed_cast >(fn))(plb); + ss.set_stack(prev_stack); + } + catch(const dispatchkit::dispatch_error &e){ + ss.set_stack(prev_stack); + throw EvalError("Engine error: " + std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]); + } + catch(ReturnValue &rv) { + ss.set_stack(prev_stack); + retval = rv.retval; + } + catch(...) { + ss.set_stack(prev_stack); + throw; + } + + return retval; + } + + template + dispatchkit::Boxed_Value eval_dot_access(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + std::vector > fn; + dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack(); + dispatchkit::Dispatch_Engine::Stack new_stack; + unsigned int i, j; + + new_stack.push_back(dispatchkit::Dispatch_Engine::Scope()); + + //todo: Please extract a single way of doing function calls between this and eval_fun_call + + retval = eval_token(ss, node->children[0]); + if (node->children.size() > 1) { + for (i = 1; i < node->children.size(); ++i) { dispatchkit::Param_List_Builder plb; plb << retval; - try { - retval = dispatch(ss.get_function(node->children[0]->text), plb); - } - catch(std::exception &e){ - throw EvalError("Can not find appropriate prefix", node->children[0]); - } - } - break; - case (Token_Type::Inline_Array) : { - try { - retval = dispatch(ss.get_function("Vector"), dispatchkit::Param_List_Builder()); - if (node->children.size() > 0) { - for (i = 0; i < node->children[0]->children.size(); ++i) { - try { - dispatchkit::Boxed_Value tmp = eval_token(ss, node->children[0]->children[i]); - dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << tmp); - } - catch (const dispatchkit::dispatch_error &inner_e) { - throw EvalError("Can not find appropriate 'push_back'", node->children[0]->children[i]); - } - } + if (node->children[i]->children.size() > 1) { + for (j = 0; j < node->children[i]->children[1]->children.size(); ++j) { + plb << eval_token(ss, node->children[i]->children[1]->children[j]); } } - catch (const dispatchkit::dispatch_error &e) { - throw EvalError("Can not find appropriate 'Vector()'", node); - } - } - break; - case (Token_Type::Inline_Range) : { - try { - retval = dispatch(ss.get_function("generate_range"), dispatchkit::Param_List_Builder() - << eval_token(ss, node->children[0]->children[0]->children[0]) - << eval_token(ss, node->children[0]->children[0]->children[1])); - } - catch (const dispatchkit::dispatch_error &e) { - throw EvalError("Unable to generate range vector", node); - } - } - break; - case (Token_Type::Inline_Map) : { - try { - retval = dispatch(ss.get_function("Map"), dispatchkit::Param_List_Builder()); - for (i = 0; i < node->children[0]->children.size(); ++i) { - try { - dispatchkit::Boxed_Value key = eval_token(ss, node->children[0]->children[i]->children[0]); - dispatchkit::Boxed_Value slot = dispatch(ss.get_function("[]"), dispatchkit::Param_List_Builder() << retval << key); - dispatch(ss.get_function("="), dispatchkit::Param_List_Builder() << slot << eval_token(ss, node->children[0]->children[i]->children[1])); - } - catch (const dispatchkit::dispatch_error &inner_e) { - throw EvalError("Can not find appropriate '=' for map init", node->children[0]->children[i]); - } - } - } - catch (const dispatchkit::dispatch_error &e) { - throw EvalError("Can not find appropriate 'Map()'", node); - } - } - break; - case (Token_Type::Fun_Call) : { - dispatchkit::Param_List_Builder plb; - //std::vector > fn; - dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack(); + std::string fun_name; + if (node->children[i]->identifier == Token_Type::Fun_Call) { + fun_name = node->children[i]->children[0]->text; + } + else { + fun_name = node->children[i]->text; + } - dispatchkit::Dispatch_Engine::Stack new_stack; - new_stack.push_back(dispatchkit::Dispatch_Engine::Scope()); - - if ((node->children.size() > 1) && (node->children[1]->identifier == Token_Type::Arg_List)) { - for (i = 0; i < node->children[1]->children.size(); ++i) { - plb << eval_token(ss, node->children[1]->children[i]); - } - } - dispatchkit::Boxed_Value fn; try { - fn = eval_token(ss, node->children[0]); - } - catch(EvalError &ee) { - ss.set_stack(prev_stack); - throw EvalError(ee.reason, node->children[0]); - } - try { - //fn = ss.get_function(node->children[0]->text); + fn = ss.get_function(fun_name); ss.set_stack(new_stack); - //retval = dispatch(fn, plb); - //retval = dispatch - retval = (*dispatchkit::boxed_cast >(fn))(plb); + retval = dispatch(fn, plb); ss.set_stack(prev_stack); } catch(const dispatchkit::dispatch_error &e){ ss.set_stack(prev_stack); - throw EvalError("Engine error: " + std::string(e.what()) + " with function '" + node->children[0]->text + "'", node->children[0]); + throw EvalError("Can not find appropriate '" + fun_name + "'", node); } catch(ReturnValue &rv) { ss.set_stack(prev_stack); @@ -326,263 +431,357 @@ namespace chaiscript throw; } } - break; + } - case (Token_Type::Dot_Access) : { - std::vector > fn; - dispatchkit::Dispatch_Engine::Stack prev_stack = ss.get_stack(); + return retval; + } - dispatchkit::Dispatch_Engine::Stack new_stack; - new_stack.push_back(dispatchkit::Dispatch_Engine::Scope()); - - retval = eval_token(ss, node->children[0]); - if (node->children.size() > 1) { - for (i = 1; i < node->children.size(); ++i) { - dispatchkit::Param_List_Builder plb; - plb << retval; - - if (node->children[i]->children.size() > 1) { - //std::cout << "size: " << node->children[i]->children.size() << std::endl; - for (j = 0; j < node->children[i]->children[1]->children.size(); ++j) { - plb << eval_token(ss, node->children[i]->children[1]->children[j]); - } - } - - std::string fun_name; - if (node->children[i]->identifier == Token_Type::Fun_Call) { - fun_name = node->children[i]->children[0]->text; - } - else { - fun_name = node->children[i]->text; - } + template + dispatchkit::Boxed_Value eval_if(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + retval = eval_token(ss, node->children[0]); + bool cond; + try { + cond = dispatchkit::boxed_cast(retval); + } + catch (std::exception &e) { + throw EvalError("If condition not boolean", node->children[0]); + } + if (cond) { + retval = eval_token(ss, node->children[1]); + } + else { + if (node->children.size() > 2) { + i = 2; + while ((!cond) && (i < node->children.size())) { + if (node->children[i]->text == "else") { + retval = eval_token(ss, node->children[i+1]); + cond = true; + } + else if (node->children[i]->text == "elseif") { + retval = eval_token(ss, node->children[i+1]); try { - fn = ss.get_function(fun_name); - ss.set_stack(new_stack); - retval = dispatch(fn, plb); - ss.set_stack(prev_stack); + cond = dispatchkit::boxed_cast(retval); } - catch(const dispatchkit::dispatch_error &e){ - ss.set_stack(prev_stack); - throw EvalError("Can not find appropriate '" + fun_name + "'", node); + catch (std::exception &e) { + throw EvalError("Elseif condition not boolean", node->children[i+1]); } - catch(ReturnValue &rv) { - ss.set_stack(prev_stack); - retval = rv.retval; - } - catch(...) { - ss.set_stack(prev_stack); - throw; + if (cond) { + retval = eval_token(ss, node->children[i+2]); } } + i = i + 3; } } - break; + } - case(Token_Type::If) : { + return retval; + } + + template + dispatchkit::Boxed_Value eval_while(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + + retval = eval_token(ss, node->children[0]); + bool cond; + try { + cond = dispatchkit::boxed_cast(retval); + } + catch (std::exception) { + throw EvalError("While condition not boolean", node->children[0]); + } + while (cond) { + try { + eval_token(ss, node->children[1]); retval = eval_token(ss, node->children[0]); - bool cond; - try { - cond = dispatchkit::boxed_cast(retval); - } - catch (std::exception &e) { - throw EvalError("If condition not boolean", node->children[0]); - } - if (cond) { - retval = eval_token(ss, node->children[1]); - } - else { - if (node->children.size() > 2) { - i = 2; - while ((!cond) && (i < node->children.size())) { - if (node->children[i]->text == "else") { - retval = eval_token(ss, node->children[i+1]); - cond = true; - } - else if (node->children[i]->text == "elseif") { - retval = eval_token(ss, node->children[i+1]); - try { - cond = dispatchkit::boxed_cast(retval); - } - catch (std::exception &e) { - throw EvalError("Elseif condition not boolean", node->children[i+1]); - } - if (cond) { - retval = eval_token(ss, node->children[i+2]); - } - } - i = i + 3; - } - } - } - } - break; - case(Token_Type::While) : { - retval = eval_token(ss, node->children[0]); - bool cond; try { cond = dispatchkit::boxed_cast(retval); } catch (std::exception) { throw EvalError("While condition not boolean", node->children[0]); } - while (cond) { - try { - eval_token(ss, node->children[1]); - retval = eval_token(ss, node->children[0]); - try { - cond = dispatchkit::boxed_cast(retval); - } - catch (std::exception) { - throw EvalError("While condition not boolean", node->children[0]); - } - } - catch (BreakLoop &bl) { - cond = false; - } - } - retval = dispatchkit::Boxed_Value(); } - break; - case(Token_Type::For) : { - dispatchkit::Boxed_Value condition; - bool cond; - - try { - if (node->children.size() == 4) { - eval_token(ss, node->children[0]); - condition = eval_token(ss, node->children[1]); - } - else if (node->children.size() == 3){ - condition = eval_token(ss, node->children[0]); - } - cond = dispatchkit::boxed_cast(condition); - } - catch (std::exception &e) { - throw EvalError("For condition not boolean", node); - } - while (cond) { - try { - if (node->children.size() == 4) { - eval_token(ss, node->children[3]); - eval_token(ss, node->children[2]); - condition = eval_token(ss, node->children[1]); - } - else if (node->children.size() == 3) { - eval_token(ss, node->children[2]); - eval_token(ss, node->children[1]); - condition = eval_token(ss, node->children[0]); - } - cond = dispatchkit::boxed_cast(condition); - - } - catch (std::exception &e) { - throw EvalError("For condition not boolean", node); - } - catch (BreakLoop &bl) { - cond = false; - } - } - retval = dispatchkit::Boxed_Value(); + catch (BreakLoop &bl) { + cond = false; } - break; - case (Token_Type::Def) : { - std::vector param_names; - std::string annotation = node->annotation?node->annotation->text:""; - boost::shared_ptr guard; - size_t numparams = 0; - std::string function_name = node->children[0]->text; - TokenPtr guardnode; + } + return dispatchkit::Boxed_Value(); + } - if ((node->children.size() > 2) && (node->children[1]->identifier == Token_Type::Arg_List)) { - numparams = node->children[1]->children.size(); - for (i = 0; i < numparams; ++i) { - param_names.push_back(node->children[1]->children[i]->text); - } + template + dispatchkit::Boxed_Value eval_for(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; - if (node->children.size() > 3) { - guardnode = node->children[2]; - } + dispatchkit::Boxed_Value condition; + bool cond; + + try { + if (node->children.size() == 4) { + eval_token(ss, node->children[0]); + condition = eval_token(ss, node->children[1]); + } + else if (node->children.size() == 3){ + condition = eval_token(ss, node->children[0]); + } + cond = dispatchkit::boxed_cast(condition); + } + catch (std::exception &e) { + throw EvalError("For condition not boolean", node); + } + while (cond) { + try { + if (node->children.size() == 4) { + eval_token(ss, node->children[3]); + eval_token(ss, node->children[2]); + condition = eval_token(ss, node->children[1]); } - else { - //no parameters - numparams = 0; - - if (node->children.size() > 2) { - guardnode = node->children[1]; - } + else if (node->children.size() == 3) { + eval_token(ss, node->children[2]); + eval_token(ss, node->children[1]); + condition = eval_token(ss, node->children[0]); } - - if (guardnode) { - guard = boost::shared_ptr - (new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function, - boost::ref(ss), guardnode, - param_names, _1), numparams)); - } - - ss.register_function(boost::shared_ptr - (new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function, - boost::ref(ss), node->children.back(), - param_names, _1), numparams, - annotation, guard)), function_name); + cond = dispatchkit::boxed_cast(condition); } - break; - case (Token_Type::Lambda) : { - std::vector param_names; - size_t numparams = 0; - - if ((node->children.size() > 0) && (node->children[0]->identifier == Token_Type::Arg_List)) { - numparams = node->children[0]->children.size(); - for (i = 0; i < numparams; ++i) { - param_names.push_back(node->children[0]->children[i]->text); - } - - } - else { - //no parameters - numparams = 0; - } - - retval = dispatchkit::Boxed_Value(boost::shared_ptr( - new dispatchkit::Dynamic_Proxy_Function( - boost::bind(&eval_function, boost::ref(ss), node->children.back(), param_names, _1), numparams))); + catch (std::exception &e) { + throw EvalError("For condition not boolean", node); } - break; + catch (BreakLoop &bl) { + cond = false; + } + } + return dispatchkit::Boxed_Value(); + } - case (Token_Type::Block) : { - ss.new_scope(); - for (i = 0; i < node->children.size(); ++i) { - try { - retval = eval_token(ss, node->children[i]); - } - catch (const chaiscript::ReturnValue &rv) { - ss.pop_scope(); - retval = rv.retval; - throw; - } - catch (...) { - ss.pop_scope(); - throw; - } - } + template + dispatchkit::Boxed_Value eval_def(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + std::vector param_names; + std::string annotation = node->annotation?node->annotation->text:""; + boost::shared_ptr guard; + size_t numparams = 0; + std::string function_name = node->children[0]->text; + TokenPtr guardnode; + + if ((node->children.size() > 2) && (node->children[1]->identifier == Token_Type::Arg_List)) { + numparams = node->children[1]->children.size(); + for (i = 0; i < numparams; ++i) { + param_names.push_back(node->children[1]->children[i]->text); + } + + if (node->children.size() > 3) { + guardnode = node->children[2]; + } + } + else { + //no parameters + numparams = 0; + + if (node->children.size() > 2) { + guardnode = node->children[1]; + } + } + + if (guardnode) { + guard = boost::shared_ptr + (new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function, + boost::ref(ss), guardnode, + param_names, _1), numparams)); + } + + ss.register_function(boost::shared_ptr + (new dispatchkit::Dynamic_Proxy_Function(boost::bind(&eval_function, + boost::ref(ss), node->children.back(), + param_names, _1), numparams, + annotation, guard)), function_name); + + return retval; + } + + template + dispatchkit::Boxed_Value eval_lambda(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + std::vector param_names; + size_t numparams = 0; + + if ((node->children.size() > 0) && (node->children[0]->identifier == Token_Type::Arg_List)) { + numparams = node->children[0]->children.size(); + for (i = 0; i < numparams; ++i) { + param_names.push_back(node->children[0]->children[i]->text); + } + + } + else { + //no parameters + numparams = 0; + } + + return dispatchkit::Boxed_Value(boost::shared_ptr( + new dispatchkit::Dynamic_Proxy_Function( + boost::bind(&eval_function, boost::ref(ss), node->children.back(), param_names, _1), numparams))); + } + + template + dispatchkit::Boxed_Value eval_block(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + unsigned int i; + + ss.new_scope(); + for (i = 0; i < node->children.size(); ++i) { + try { + retval = eval_token(ss, node->children[i]); + } + catch (const chaiscript::ReturnValue &rv) { ss.pop_scope(); + retval = rv.retval; + throw; } + catch (...) { + ss.pop_scope(); + throw; + } + } + ss.pop_scope(); + + return retval; + } + + template + dispatchkit::Boxed_Value eval_return(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + if (node->children.size() > 0) { + retval = eval_token(ss, node->children[0]); + } + else { + retval = dispatchkit::Boxed_Value(); + } + throw ReturnValue(retval, node); + } + + template + dispatchkit::Boxed_Value eval_break(Eval_System &ss, TokenPtr node) { + throw BreakLoop(node); + } + + template + dispatchkit::Boxed_Value eval_token(Eval_System &ss, TokenPtr node) { + dispatchkit::Boxed_Value retval; + + switch (node->identifier) { + case (Token_Type::File) : + retval = eval_file(ss, node); break; - case (Token_Type::Return) : { - if (node->children.size() > 0) { - retval = eval_token(ss, node->children[0]); - } - else { - retval = dispatchkit::Boxed_Value(); - } - throw ReturnValue(retval, node); - } + case (Token_Type::Id) : + retval = eval_id(ss, node); break; - case (Token_Type::Break) : { - throw BreakLoop(node); - } + + case (Token_Type::Float) : + retval = eval_float(ss, node); + break; + + case (Token_Type::Int) : + retval = eval_int(ss, node); + break; + + case (Token_Type::Quoted_String) : + retval = eval_quoted_string(ss, node); + break; + + case (Token_Type::Single_Quoted_String) : + retval = eval_single_quoted_string(ss, node); + break; + + case (Token_Type::Equation) : + retval = eval_equation(ss, node); + break; + + case (Token_Type::Var_Decl) : + retval = eval_var_decl(ss, node); + break; + + case (Token_Type::Expression) : + retval = eval_expression(ss, node); + break; + + case (Token_Type::Comparison) : + case (Token_Type::Additive) : + case (Token_Type::Multiplicative) : + retval = eval_comp_add_mul(ss, node); + break; + + case (Token_Type::Array_Call) : + retval = eval_array_call(ss, node); + break; + + case (Token_Type::Negate) : + retval = eval_negate(ss, node); + break; + + case (Token_Type::Not) : + retval = eval_not(ss, node); + break; + + case (Token_Type::Prefix) : + retval = eval_prefix(ss, node); + break; + + case (Token_Type::Inline_Array) : + retval = eval_inline_array(ss, node); + break; + + case (Token_Type::Inline_Range) : + retval = eval_inline_range(ss, node); + break; + + case (Token_Type::Inline_Map) : + retval = eval_inline_map(ss, node); + break; + + case (Token_Type::Fun_Call) : + retval = eval_fun_call(ss, node); + break; + + case (Token_Type::Dot_Access) : + retval = eval_dot_access(ss, node); + break; + + case(Token_Type::If) : + retval = eval_if(ss, node); + break; + + case(Token_Type::While) : + retval = eval_while(ss, node); + break; + + case(Token_Type::For) : + retval = eval_for(ss, node); + break; + + case (Token_Type::Def) : + retval = eval_def(ss, node); + break; + + case (Token_Type::Lambda) : + retval = eval_lambda(ss, node); + break; + + case (Token_Type::Block) : + retval = eval_block(ss, node); + break; + + case (Token_Type::Return) : + retval = eval_return(ss, node); + break; + + case (Token_Type::Break) : + retval = eval_break(ss, node); break; } diff --git a/samples/sensors.chai b/samples/sensors.chai index be9e4b9..2cf108f 100644 --- a/samples/sensors.chai +++ b/samples/sensors.chai @@ -56,7 +56,7 @@ def update_state(state) update_cpu_state(state, file, "cpu1"); } -dump_system() +//dump_system() var global_state = Map() diff --git a/unittests/eval.chai b/unittests/eval.chai new file mode 100644 index 0000000..189513c --- /dev/null +++ b/unittests/eval.chai @@ -0,0 +1 @@ +print(eval("3 + 4")) diff --git a/unittests/eval.txt b/unittests/eval.txt new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/unittests/eval.txt @@ -0,0 +1 @@ +7 diff --git a/unittests/return.chai b/unittests/return.chai index 12cba5e..49cce12 100644 --- a/unittests/return.chai +++ b/unittests/return.chai @@ -1,5 +1,5 @@ -def bob() { +def sam() { return 5 } -print(bob()) +print(sam())