diff --git a/src/generator.h b/src/generator.h index 9cff769..115ec17 100644 --- a/src/generator.h +++ b/src/generator.h @@ -203,16 +203,27 @@ private: previous_result = nullptr; } + // rename me to current_field() const std::wstring & current_name() { return (field_index == 0)? name : fields[field_index - 1]; } + const std::wstring & next_field() + { + return fields[field_index]; + } + bool is_last_field() { return field_index == fields.size(); } + bool is_next_field() + { + return field_index < fields.size(); + } + }; struct BlockStack @@ -360,7 +371,7 @@ private: pt::Space * CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, pt::Space & space, FindHelper & find_helper, size_t model_wrapper_space_table_index); - bool CallSpace(morm::SpaceWrapper & space_wrapper, FindHelper & find_helper); + bool CallSpaceWrapper(morm::SpaceWrapper & space_wrapper, FindHelper & find_helper); bool CallSpace(pt::Space & root_space, FindHelper & find_helper); @@ -377,7 +388,8 @@ private: void FindVariable(FindHelper & find_helper); void EvaluateVariable(FindHelper & find_helper); - bool EvaluateModelField(FindHelper & find_helper); + bool EvaluateModel(FindHelper & find_helper); + bool EvaluateModelWrapper(FindHelper & find_helper); void EvaluateFunction(typename Var::UserFunction user_function, FindHelper & find_helper); @@ -1428,18 +1440,18 @@ void Generator::PrintLast template -bool Generator::CallSpace( +bool Generator::CallSpaceWrapper( morm::SpaceWrapper & space_wrapper, FindHelper & find_helper) { pt::Space * space = space_wrapper.get_space(); size_t model_wrapper_space_table_index = 0; //space_wrapper.set_last_for_loop_status(false); - while( find_helper.field_index < find_helper.fields.size() ) + while( find_helper.is_next_field() ) { if( space->is_object() ) { - const std::wstring & next_field = find_helper.fields[find_helper.field_index]; + const std::wstring & next_field = find_helper.next_field(); pt::Space * next_space = space->get_space(next_field); if( next_space ) @@ -1459,7 +1471,7 @@ bool Generator::CallSpace { if( model_wrapper_space_table_index < space_wrapper.space_indices_table_size() ) { - std::wstring & next_field = find_helper.fields[find_helper.field_index]; + const std::wstring & next_field = find_helper.next_field(); if( next_field == L"first" ) { @@ -1499,7 +1511,9 @@ bool Generator::CallSpace if( !next_space ) { // a [for ...] was not used beforehand - return false; + // return true, this can be a global method such as 'size' + find_helper.result->set(*space, false); + return true; } @@ -1612,8 +1626,10 @@ bool Generator::CallSpace else if( space->is_table() ) { - CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message - return false; + //CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message + //return false; + find_helper.result->set(*space, false); + return true; } else { @@ -1623,8 +1639,10 @@ bool Generator::CallSpace if( space->is_table() ) { - CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message - return false; +// CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message +// return false; + find_helper.result->set(*space, false); + return true; } else if( !IsTestingFunctionExistence() ) @@ -1946,9 +1964,7 @@ void Generator::FindVaria if( find_helper.found ) { - if( find_helper.result->type != Var::TYPE_MODEL && - find_helper.result->type != Var::TYPE_MODEL_CONTAINER_WRAPPER && - find_helper.result->type != Var::TYPE_SPACE_WRAPPER ) // TYPE_SPACE here too? + if( find_helper.result->type != Var::TYPE_MODEL ) // TYPE_SPACE here too? { find_helper.input = find_helper.result; } @@ -1982,30 +1998,15 @@ void Generator::FindVaria template void Generator::EvaluateVariable(FindHelper & find_helper) { - Var * result_child = nullptr; + bool was_child_found = false; find_helper.found = false; find_helper.current_var = nullptr; const std::wstring & name = find_helper.current_name(); if( find_helper.previous_var ) { - if( find_helper.previous_var->type == Var::TYPE_MODEL_CONTAINER_WRAPPER && name == L"val" && find_helper.field_index < find_helper.fields.size() ) - { - const std::wstring & next_name = find_helper.fields[find_helper.field_index]; - find_helper.current_var = find_helper.previous_var->find_child(next_name); - - if( find_helper.current_var != nullptr ) - { - find_helper.field_index += 1; - } - } - else - { - find_helper.current_var = find_helper.previous_var->find_child(name); - } - - result_child = find_helper.current_var; - find_helper.found = (find_helper.current_var != nullptr); + find_helper.current_var = find_helper.previous_var->find_child(name); + find_helper.found = was_child_found = (find_helper.current_var != nullptr); if( find_helper.current_var ) *find_helper.result = *find_helper.current_var; @@ -2014,11 +2015,14 @@ void Generator::EvaluateV if( !find_helper.found && find_helper.previous_name && find_helper.previous_result ) { - if( find_helper.previous_result->type == Var::TYPE_MODEL || - find_helper.previous_result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER ) + if( find_helper.previous_result->type == Var::TYPE_MODEL ) { - if( !EvaluateModelField(find_helper) ) + // let functions return false to immediately return + // and find_helper can be either true or false + if( !EvaluateModel(find_helper) ) return; + + // what about if EvaluateModel returns another model or a space? we need a loop here? } else if( find_helper.previous_result->type == Var::TYPE_SPACE ) @@ -2029,7 +2033,7 @@ void Generator::EvaluateV } // find_helper.field_index could have been changed by EvaluateModelField or CallSpace - if( find_helper.field_index < find_helper.fields.size() + 1 ) + if( find_helper.field_index < find_helper.fields.size() + 1 ) // add 'has_current_field()' to FindHelper { const std::wstring & name = find_helper.current_name(); @@ -2065,7 +2069,7 @@ void Generator::EvaluateV find_helper.result->type = Var::Type::TYPE_STREAM; } - if( find_helper.previous_var && !result_child ) + if( find_helper.previous_var && !was_child_found ) { // may only model_container_wrapper and space_wrapper here? //find_helper.result->type == Var::TYPE_MODEL || @@ -2074,34 +2078,22 @@ void Generator::EvaluateV find_helper.result->type == Var::TYPE_SPACE_WRAPPER || find_helper.result->type == Var::TYPE_FUNCTION ) { - result_child = find_helper.previous_var->add_child(name, *find_helper.result); + + find_helper.previous_var->add_child(name, *find_helper.result); + // this result_child probably should be set as find_helper.current_var } } - if( find_helper.result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER && find_helper.result->model_container_wrapper ) + if( find_helper.result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER ) { - if( find_helper.is_last_field() && is_generating_for ) - { - find_helper.result->model_container_wrapper->increment_iterator(); - bool loop_status = find_helper.result->model_container_wrapper->is_iterator_correct(); - find_helper.result->set(loop_status); - - // find_helper.result was copied from currrent_var so it doesn't have childs here...(childs are not copied) - if( find_helper.current_var ) - find_helper.current_var->clear_childs(); - - // but it only clears child in the first level, is it correct? - // childs from different vars will not be cleared - } + if( !EvaluateModelWrapper(find_helper) ) + return; } - - if( result_child ) + else + if( find_helper.result->type == Var::TYPE_SPACE_WRAPPER ) { - if( result_child->type == Var::TYPE_SPACE_WRAPPER && result_child->space_wrapper ) - { - find_helper.result->clear(); - find_helper.found = CallSpace(*result_child->space_wrapper, find_helper); - } + if( !CallSpaceWrapper(*find_helper.result->space_wrapper, find_helper) ) + return; } find_helper.previous_var = find_helper.current_var; @@ -2116,51 +2108,11 @@ void Generator::EvaluateV } + template -bool Generator::EvaluateModelField(FindHelper & find_helper) +bool Generator::EvaluateModel(FindHelper & find_helper) { - if( find_helper.previous_result->type == Var::TYPE_MODEL ) - { - //find_helper.result->clear(); - find_helper.found = CallModelField(*find_helper.previous_result->model, find_helper); - } - else - if( find_helper.previous_result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER ) - { - //find_helper.result->clear(); - - const std::wstring & cur_field = find_helper.current_name(); - - // make a constant somewhere - if( cur_field == L"val" ) - { - find_helper.field_index += 1; - - morm::Model * model = find_helper.previous_result->model_container_wrapper->get_model(); - - if( model ) - { -// find_helper.result->set(*model); -// find_helper.found = true; - - find_helper.found = CallModelField(*model, find_helper); - - } - else - { - // put some log (no [for] statement) - // CreateMsg(L"model ", name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); - find_helper.found = false; - return false; - } - } - else - { - // may cur_fiels is a global function, return true - find_helper.found = false; - return true; - } - } + find_helper.found = CallModelField(*find_helper.previous_result->model, find_helper); if( find_helper.found ) { @@ -2177,6 +2129,57 @@ bool Generator::EvaluateM } +template +bool Generator::EvaluateModelWrapper(FindHelper & find_helper) +{ + if( find_helper.is_last_field() ) + { + if( is_generating_for ) + { + find_helper.result->model_container_wrapper->increment_iterator(); + bool loop_status = find_helper.result->model_container_wrapper->is_iterator_correct(); + + find_helper.result->set(loop_status); // may create a second bool status only for loops? + + // find_helper.result was copied from currrent_var so it doesn't have childs here...(childs are not copied) + if( find_helper.current_var ) + find_helper.current_var->clear_childs(); + + // but it only clears child in the first level, is it correct? + // childs from different vars will not be cleared + } + } + else + if( find_helper.is_next_field() ) + { + const std::wstring & next_field = find_helper.next_field(); + + // make a constant somewhere + if( next_field == L"val" ) + { + find_helper.field_index += 1; + morm::Model * model = find_helper.result->model_container_wrapper->get_model(); + + if( model ) + { + find_helper.result->set(*model); + find_helper.found = true; + } + else + { + // put some log (no [for] statement) + // CreateMsg(L"model ", name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); + find_helper.result->clear(); + find_helper.found = false; + return false; + } + } + } + + return true; +} + + template void Generator::EvaluateFunction(typename Var::UserFunction user_function, FindHelper & find_helper) @@ -2733,7 +2736,23 @@ void Generator::MakeTextF { if( output_stream ) { - result.serialize_to(*output_stream); + if( result.type == Var::TYPE_MODEL_CONTAINER_WRAPPER ) + { + // IMPROVEME add model_container serialized as a table + // add a method 'serialize_to' to ModelContainerWrapper + } + else + if( result.type == Var::TYPE_MODEL ) + { + // IMPROVEME get rid of the tmp object + pt::TextStream str_tmp; + result.model->to_text(str_tmp); + *output_stream << str_tmp; // what about escaping here? + } + else + { + result.serialize_to(*output_stream); + } } } diff --git a/src/var.h b/src/var.h index deccca5..4934a56 100644 --- a/src/var.h +++ b/src/var.h @@ -47,8 +47,6 @@ namespace morm { class Model; - class ModelContainerWrapper; - class SpaceWrapper; } @@ -868,10 +866,6 @@ void Var::serialize_to(pt::WTextStream & str) switch(type) { case TYPE_SPACE_LOCAL: -// case TYPE_BOOL: -// case TYPE_LONG: -// case TYPE_DOUBLE: -// case TYPE_STRING: space_local.serialize_to_string(str); break; @@ -885,8 +879,11 @@ void Var::serialize_to(pt::WTextStream & str) case TYPE_VOID: case TYPE_FUNCTION: + break; + case TYPE_MODEL: case TYPE_MODEL_CONTAINER_WRAPPER: + // 'model' is a forward declaration, we cannot call 'to_text' method break; case TYPE_SPACE_WRAPPER: