diff --git a/CMakeLists.txt b/CMakeLists.txt index b38de34..f617b9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,7 +180,7 @@ if(BUILD_TESTING) add_executable(short_comparison_test unittests/short_comparison_test.cpp) target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS}) - add_test(NAME short_comparison_test COMMAND short_comparison_test) + add_test(NAME Short_Comparison_Test COMMAND short_comparison_test) add_executable(cpp_lambda_test unittests/cpp_lambda_test.cpp) target_link_libraries(cpp_lambda_test ${LIBS} ${EXTRA_LINKER_FLAGS}) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 8428265..964c29c 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -64,7 +64,6 @@ namespace chaiscript void *m_data_ptr; const void *m_const_data_ptr; bool m_is_ref; - std::vector > m_dependencies; }; struct Object_Data @@ -235,24 +234,6 @@ namespace chaiscript return !is_ref(); } - void clear_dependencies() - { - m_data->m_dependencies.clear(); - } - - template - void add_dependencies(InItr begin, const InItr &end) - { - while (begin != end) - { - if (begin->m_data != m_data) - { - m_data->m_dependencies.push_back(begin->m_data); - } - ++begin; - } - } - void *get_ptr() const { return m_data->m_data_ptr; diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index b3db73c..625b855 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "boxed_value.hpp" @@ -896,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: /** @@ -1082,6 +1106,7 @@ namespace chaiscript struct Stack_Holder { Stack_Holder() + : call_depth(0) { Stack s(new StackData()); s->push_back(Scope()); @@ -1089,6 +1114,9 @@ namespace chaiscript } std::deque stacks; + + std::list call_params; + int call_depth; }; std::vector m_conversions; diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 4f65510..69f77af 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -43,7 +43,6 @@ namespace chaiscript Boxed_Value operator()(const std::vector ¶ms) const { Boxed_Value bv = do_call(params); - bv.add_dependencies(params.begin(), params.end()); return bv; } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index f677674..349f050 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -323,6 +323,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 { @@ -340,8 +368,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 618fd31..2b48b5d 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -183,6 +183,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); std::vector params; if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { @@ -191,6 +192,8 @@ namespace chaiscript } } + fpp.save_params(params); + try { Boxed_Value fn = this->children[0]->eval(t_ss); @@ -298,7 +301,6 @@ namespace chaiscript return retval; } else { retval = t_ss.call_function("clone", retval); - retval.clear_dependencies(); } } @@ -460,6 +462,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); std::vector params; params.push_back(retval); @@ -469,6 +472,8 @@ namespace chaiscript } } + fpp.save_params(params); + 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; @@ -883,14 +888,20 @@ 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 ~Inline_Array_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){ - std::vector vec; - if (this->children.size() > 0) { - for (size_t i = 0; i < this->children[0]->children.size(); ++i) { - vec.push_back(this->children[0]->children[i]->eval(t_ss)); + try { + std::vector vec; + if (this->children.size() > 0) { + for (size_t i = 0; i < this->children[0]->children.size(); ++i) { + Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->eval(t_ss)); + vec.push_back(bv); + } } + return const_var(vec); + } + catch (const exception::dispatch_error &) { + throw exception::eval_error("Can not find appropriate 'clone' or copy constructor for vector elements"); } - return const_var(vec); } }; @@ -904,8 +915,9 @@ namespace chaiscript try { std::map retval; for (size_t i = 0; i < this->children[0]->children.size(); ++i) { + Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss)); retval[boxed_cast(this->children[0]->children[i]->children[0]->eval(t_ss))] - = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss)); + = bv; } return const_var(retval); } diff --git a/unittests/map_inplace_init.chai b/unittests/map_inplace_init.chai index 1d88494..f86bb4f 100644 --- a/unittests/map_inplace_init.chai +++ b/unittests/map_inplace_init.chai @@ -1,3 +1,14 @@ auto x = ["bob":1, "fred":2] assert_equal(2, x.size()); + + +// Make sure vector elements are copied into place for consistency with +// map inplace construction +var i = 1; +var y = ["a":i]; + +assert_equal(1, y["a"]); +i = 3; +assert_equal(3, i); +assert_equal(1, y["a"]); diff --git a/unittests/operator_scoping.chai b/unittests/operator_scoping.chai new file mode 100644 index 0000000..e6f9272 --- /dev/null +++ b/unittests/operator_scoping.chai @@ -0,0 +1,14 @@ +def `+`(x, y) +{ + print(i); +} + +auto i = 10; + + +// It should fail because `+` should not be able to see the i + +"1" + 1; +assert_false(true); + + diff --git a/unittests/vector_inplace_init.chai b/unittests/vector_inplace_init.chai index 7b01cb9..e3bf6a3 100644 --- a/unittests/vector_inplace_init.chai +++ b/unittests/vector_inplace_init.chai @@ -1,2 +1,14 @@ auto x = [1, 2, 3] assert_equal(3, x.size()) + + + +// Make sure vector elements are copied into place for consistency with +// map inplace construction +var i = 1; +var y = [i]; + +assert_equal(1, y[0]); +i = 3; +assert_equal(3, i); +assert_equal(1, y[0]);