diff --git a/src/generator.h b/src/generator.h index 0ff12d1..b4010e9 100644 --- a/src/generator.h +++ b/src/generator.h @@ -181,6 +181,7 @@ private: bool evaluate_last; const std::wstring * previous_name; Var * previous_result; + size_t nested_calls; FindHelper(const std::wstring & name, std::vector & fields, std::vector> & parameters, Var & result): @@ -191,6 +192,7 @@ private: evaluate_last = true; previous_name = nullptr; previous_result = nullptr; + nested_calls = 0; } const std::wstring & current_name() @@ -291,6 +293,8 @@ private: bool can_use_vars; bool program_mode; + size_t max_nested_calls; + ExpressionParser * expression_parser; @@ -364,14 +368,10 @@ private: Var * FindInScope(const std::wstring & name); - void FindVariable(FindHelper & find_helper - //const std::wstring & name, std::vector & fields, size_t & field_index, std::vector> & parameters - ); - - void EvaluateVariable(FindHelper & find_helper - //const std::wstring & name, Var & var, std::vector & fields, size_t & field_index, std::vector> & parameters, Var & result - ); - + void FindVariable(FindHelper & find_helper); + void EvaluateVariable(FindHelper & find_helper); + void EvaluateModelField(FindHelper & find_helper); + void EvaluateFunction(typename Var::UserFunction user_function, FindHelper & find_helper); // bool CallVariable(FindHelper & findxxx @@ -479,6 +479,7 @@ Generator::Generator() : can_use_vars = true; expression_parser = nullptr; program_mode = false; + max_nested_calls = 64; } @@ -516,6 +517,7 @@ Generator::operator=(cons ezc_frames_stack_size = n.ezc_frames_stack_size; expression_parser = n.expression_parser; program_mode = n.program_mode; + max_nested_calls = n.max_nested_calls; // vars doesn't have to be copied @@ -1810,6 +1812,7 @@ void Generator::FindVaria find_helper.field_index = 0; find_helper.previous_name = nullptr; find_helper.previous_result = nullptr; + find_helper.nested_calls = 0; do { @@ -1838,38 +1841,12 @@ void Generator::EvaluateV if( find_helper.previous_name && find_helper.previous_result ) { - //var = find_helper.previous_result->find_child(name); + EvaluateModelField(find_helper); + } - //if( !var ) - { - if( find_helper.previous_result->type == Var::TYPE_MODEL ) - { - find_helper.found = CallModelField(*find_helper.previous_result->model, find_helper); - find_helper.previous_result = find_helper.found ? &find_helper.result : nullptr; - } - - if( find_helper.previous_result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER ) - { - morm::Model * model = find_helper.previous_result->model_container_wrapper->get_model(); - - if( model ) - { - find_helper.found = CallModelField(*model, find_helper); // parameters here? - find_helper.previous_result = find_helper.found ? &find_helper.result : nullptr; - } - else - { - // put some log (no [for] statement) - // CreateMsg(L"model ", name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); - return; - } - } - } -// else -// { -// // child found -// -// } + if( find_helper.nested_calls > max_nested_calls ) + { + return; } if( !find_helper.found ) @@ -1881,10 +1858,9 @@ void Generator::EvaluateV // if a function returns another function we should make CallFunction() again? if( var->type == Var::TYPE_FUNCTION && var->user_function ) { - CallFunction(var->user_function, find_helper); - find_helper.found = true; + EvaluateFunction(var->user_function, find_helper); } - + else if( var->type == Var::TYPE_MODEL_CONTAINER_WRAPPER && var->model_container_wrapper ) { if( find_helper.is_last_field() && is_generating_for ) @@ -1893,12 +1869,12 @@ void Generator::EvaluateV var->clear_childs(); } } - + else if( var->type == Var::TYPE_SPACE_WRAPPER && var->space_wrapper ) { find_helper.found = CallSpace(*var->space_wrapper, find_helper); } - + else if( var->type == Var::TYPE_DATE && var->date ) { if( find_helper.is_last_field() ) @@ -1923,6 +1899,90 @@ void Generator::EvaluateV } +template +void Generator::EvaluateModelField(FindHelper & find_helper) +{ + //var = find_helper.previous_result->find_child(name); + + //if( !var ) + { + if( find_helper.previous_result->type == Var::TYPE_MODEL ) + { + find_helper.found = CallModelField(*find_helper.previous_result->model, find_helper); + find_helper.previous_result = find_helper.found ? &find_helper.result : nullptr; + } + else + if( find_helper.previous_result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER ) + { + morm::Model * model = find_helper.previous_result->model_container_wrapper->get_model(); + + if( model ) + { + find_helper.found = CallModelField(*model, find_helper); // parameters here? + find_helper.previous_result = find_helper.found ? &find_helper.result : nullptr; + } + else + { + // put some log (no [for] statement) + // CreateMsg(L"model ", name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); + return; + } + } + + if( find_helper.found ) + { + if( find_helper.result.type == Var::TYPE_FUNCTION && find_helper.result.user_function ) + { + EvaluateFunction(find_helper.result.user_function, find_helper); + + if( !find_helper.found ) + return; // maximum nested calls exceeded + } + } + } +// else +// { +// // child found +// +// } +} + + + +template +void Generator::EvaluateFunction(typename Var::UserFunction user_function, FindHelper & find_helper) +{ + bool call_again; + + do + { + call_again = false; + CallFunction(user_function, find_helper); + find_helper.found = true; + + if( find_helper.result.type == Var::TYPE_FUNCTION && find_helper.result.user_function ) + { + user_function = find_helper.result.user_function; + find_helper.result.clear(); + find_helper.nested_calls += 1; + + if( find_helper.nested_calls <= max_nested_calls ) + { + call_again = true; + } + else + { + CreateMsg(L"Generator exceeded max nested calls"); + find_helper.found = false; + } + } + } + while( call_again ); +} + + + + /* template bool Generator::CallVariable(