diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 4056a2e..9269ff7 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -897,6 +897,29 @@ namespace chaiscript m_state = t_state; } + void save_function_params(const std::vector &t_params) + { + m_stack_holder->call_params.insert(m_stack_holder->call_params.begin(), t_params.begin(), t_params.end()); + } + + void new_function_call() + { + ++m_stack_holder->call_depth; + } + + void pop_function_call() + { + --m_stack_holder->call_depth; + + assert(m_stack_holder->call_depth >= 0); + + if (m_stack_holder->call_depth == 0) + { + /// \todo Critical: this needs to be smarter, memory can expand quickly + /// in tight loops involving function calls + m_stack_holder->call_params.clear(); + } + } private: /** @@ -1083,6 +1106,7 @@ namespace chaiscript struct Stack_Holder { Stack_Holder() + : call_depth(0) { Stack s(new StackData()); s->push_back(Scope()); @@ -1090,6 +1114,9 @@ namespace chaiscript } std::deque stacks; + + std::list call_params; + int call_depth; }; std::vector m_conversions; diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index ea4b747..8428c38 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -214,6 +214,34 @@ namespace chaiscript chaiscript::detail::Dispatch_Engine &m_de; }; + /// Creates a new functon call and pops it on destruction + struct Function_Push_Pop + { + Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de) + : m_de(t_de) + { + m_de.new_function_call(); + } + + ~Function_Push_Pop() + { + m_de.pop_function_call(); + } + + void save_params(const std::vector &t_params) + { + m_de.save_function_params(t_params); + } + + + private: + // explicitly unimplemented copy and assignment + Function_Push_Pop(const Function_Push_Pop &); + Function_Push_Pop& operator=(const Function_Push_Pop &); + + chaiscript::detail::Dispatch_Engine &m_de; + }; + /// Creates a new scope then pops it on destruction struct Stack_Push_Pop { @@ -231,8 +259,8 @@ namespace chaiscript private: // explicitly unimplemented copy and assignment - Stack_Push_Pop(const Scope_Push_Pop &); - Stack_Push_Pop& operator=(const Scope_Push_Pop &); + Stack_Push_Pop(const Stack_Push_Pop &); + Stack_Push_Pop& operator=(const Stack_Push_Pop &); chaiscript::detail::Dispatch_Engine &m_de; }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 66e214f..70734fb 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -182,6 +182,7 @@ namespace chaiscript AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Fun_Call_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ + chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); dispatch::Param_List_Builder plb; if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { @@ -190,6 +191,8 @@ namespace chaiscript } } + fpp.save_params(plb.objects); + Boxed_Value fn = this->children[0]->eval(t_ss); try { @@ -431,6 +434,7 @@ namespace chaiscript if (this->children.size() > 1) { for (size_t i = 2; i < this->children.size(); i+=2) { + chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); dispatch::Param_List_Builder plb; plb << retval; @@ -440,6 +444,8 @@ namespace chaiscript } } + fpp.save_params(plb.objects); + std::string fun_name; if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) { fun_name = this->children[i]->children[0]->text;