From 86d0b7d8868db8632cafcf3f964a83b2803022ac Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 23 Nov 2021 19:40:52 +0100 Subject: [PATCH] changed the semantic of [for ...] loops, we have 'val' keyword now for referencing child objects sample: [for mylist] [mylist.val] [end] before we use 'this' but only for POD simple types, now we use 'val' for all types --- src/generator.h | 406 +++++++++++++++++++++++++++++++++++------------- src/var.h | 93 ++++++++--- 2 files changed, 368 insertions(+), 131 deletions(-) diff --git a/src/generator.h b/src/generator.h index 75eff6b..9cff769 100644 --- a/src/generator.h +++ b/src/generator.h @@ -361,6 +361,8 @@ 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 CallSpace(pt::Space & root_space, FindHelper & find_helper); + #ifdef EZC_HAS_MORM_LIBRARY bool CallModelField(morm::Model & model, FindHelper & find_helper); @@ -1339,7 +1341,6 @@ void Generator::CallSpace morm::SpaceWrapper & space_wrapper, pt::Space & space, FindHelper & find_helper, size_t model_wrapper_space_table_index) { pt::Space::TableType * table = space.get_table(); - find_helper.result->set(space_wrapper); if( is_generating_for ) { @@ -1347,8 +1348,14 @@ void Generator::CallSpace space_wrapper.increment_iterator(model_wrapper_space_table_index, table->size()); space_wrapper.invalidate_iterators(model_wrapper_space_table_index + 1); size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); - bool for_status = (iterator_value < table->size()); - space_wrapper.set_last_for_loop_status(for_status); + bool loop_status = (iterator_value < table->size()); + //space_wrapper.set_last_for_loop_status(for_status); + + find_helper.result->set(loop_status); + } + else + { + find_helper.result->set(space, false); } if( !IsTestingFunctionExistence() && find_helper.is_last_field() ) @@ -1426,7 +1433,7 @@ bool Generator::CallSpace { pt::Space * space = space_wrapper.get_space(); size_t model_wrapper_space_table_index = 0; - space_wrapper.set_last_for_loop_status(false); + //space_wrapper.set_last_for_loop_status(false); while( find_helper.field_index < find_helper.fields.size() ) { @@ -1442,7 +1449,9 @@ bool Generator::CallSpace } else { - break; + // may this is a global function so return true + //find_helper.found = false; // set find_helper.found here? + return true; } } else @@ -1450,24 +1459,98 @@ bool Generator::CallSpace { if( model_wrapper_space_table_index < space_wrapper.space_indices_table_size() ) { - space = CallSpaceTableForMiddleField(space_wrapper, *space, find_helper, model_wrapper_space_table_index); + std::wstring & next_field = find_helper.fields[find_helper.field_index]; - if( !space ) + if( next_field == L"first" ) + { + find_helper.field_index += 1; + + if( space->table_size() > 0 ) + { + find_helper.result->set(*space->value.value_table.front(), false); + return true; + } + else + { + CreateMsg(L"first is used but the table is empty"); // IMPROVE the warning message + return false; + } + } + else + if( next_field == L"last" ) + { + find_helper.field_index += 1; + + if( space->table_size() > 0 ) + { + find_helper.result->set(*space->value.value_table.back(), false); + return true; + } + else + { + CreateMsg(L"last is used but the table is empty"); // IMPROVE the warning message + return false; + } + } + + + pt::Space * next_space = CallSpaceTableForMiddleField(space_wrapper, *space, find_helper, model_wrapper_space_table_index); + + if( !next_space ) { // a [for ...] was not used beforehand return false; } - // increment field_index only if next_field is 'this' and space is not an object - if( !space->is_object() ) - { - std::wstring & next_field = find_helper.fields[find_helper.field_index]; - if( next_field == L"this" ) - { - find_helper.field_index += 1; - } + // put a constant somewhere + if( next_field == L"val" ) + { + find_helper.field_index += 1; } + else + if( next_field == L"index" ) + { + find_helper.field_index += 1; + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + find_helper.result->set(static_cast(iterator_value)); + return true; + break; + } + else + if( next_field == L"index-one" ) + { + find_helper.field_index += 1; + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + find_helper.result->set(static_cast(iterator_value + 1)); + return true; + break; + } + else + if( next_field == L"is_first" ) + { + find_helper.field_index += 1; + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + find_helper.result->set(iterator_value == 0); + return true; + break; + } + else + if( next_field == L"is_last" ) + { + find_helper.field_index += 1; + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + find_helper.result->set(iterator_value + 1 == space->table_size()); + return true; + break; + } + else + { + space = next_space; + break; + } + + space = next_space; } else { @@ -1490,7 +1573,8 @@ bool Generator::CallSpace else if( !IsTestingFunctionExistence() ) { - PrintLastSpaceField(*space, find_helper); + //PrintLastSpaceField(*space, find_helper); + find_helper.result->set(*space, false); // WARNING here a new space wrapper will be created, need to invastigate if( find_helper.is_last_field() ) DumpSpaceIfNeeded(*space, find_helper); @@ -1500,6 +1584,61 @@ bool Generator::CallSpace } +template +bool Generator::CallSpace( + pt::Space & root_space, FindHelper & find_helper) +{ + pt::Space * space = &root_space; + + while( find_helper.field_index < find_helper.fields.size() + 1) + { + if( space->is_object() ) + { + const std::wstring & next_field = find_helper.fields[find_helper.field_index - 1]; + pt::Space * next_space = space->get_space(next_field); + + if( next_space ) + { + find_helper.field_index += 1; + space = next_space; + } + else + { + // may this is a global function so return true + //find_helper.found = false; // set find_helper.found here? + return true; + } + } + 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; + } + else + { + break; + } + } + + 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; + } + else + if( !IsTestingFunctionExistence() ) + { + //PrintLastSpaceField(*space, find_helper); + find_helper.result->set(*space, false); + + if( find_helper.is_last_field() ) + DumpSpaceIfNeeded(*space, find_helper); + } + + return true; +} + #ifdef EZC_HAS_MORM_LIBRARY @@ -1809,12 +1948,16 @@ void Generator::FindVaria { 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 ) + find_helper.result->type != Var::TYPE_SPACE_WRAPPER ) // TYPE_SPACE here too? { find_helper.input = find_helper.result; } - find_helper.previous_name = &find_helper.current_name(); + if( find_helper.field_index == 0 || find_helper.field_index - 1 < find_helper.fields.size() ) + find_helper.previous_name = &find_helper.current_name(); + else + find_helper.previous_name = nullptr; + find_helper.field_index += 1; // for space @@ -1846,12 +1989,27 @@ void Generator::EvaluateV if( find_helper.previous_var ) { - find_helper.current_var = find_helper.previous_var->find_child(name); + 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); if( find_helper.current_var ) *find_helper.result = *find_helper.current_var; + } if( !find_helper.found && find_helper.previous_name && find_helper.previous_result ) @@ -1860,86 +2018,100 @@ void Generator::EvaluateV find_helper.previous_result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER ) { if( !EvaluateModelField(find_helper) ) - return; // is the return here needed? may set find_helper.found? + return; + } + else + if( find_helper.previous_result->type == Var::TYPE_SPACE ) + { + if( !CallSpace(*find_helper.previous_result->space, find_helper) ) + return; } } - if( !find_helper.found ) + // find_helper.field_index could have been changed by EvaluateModelField or CallSpace + if( find_helper.field_index < find_helper.fields.size() + 1 ) { - find_helper.result->clear(); // is this clear here needed? - find_helper.current_var = FindInScope(name); - find_helper.found = (find_helper.current_var != nullptr); + const std::wstring & name = find_helper.current_name(); - if( find_helper.current_var ) - *find_helper.result = *find_helper.current_var; + if( !find_helper.found ) + { + find_helper.result->clear(); // is this clear here needed? + find_helper.current_var = FindInScope(name); + find_helper.found = (find_helper.current_var != nullptr); + + if( find_helper.current_var ) + *find_helper.result = *find_helper.current_var; + + if( find_helper.found ) + { + if( find_helper.current_var->type == Var::TYPE_FUNCTION && find_helper.current_var->user_function ) + { + EvaluateFunction(find_helper.current_var->user_function, find_helper); + } + else + if( find_helper.current_var->type == Var::TYPE_DATE && find_helper.current_var->date ) + { + // move me below (where TYPE_MODEL_CONTAINER_WRAPPER is used) + if( find_helper.is_last_field() ) + PrintDate(*find_helper.current_var->date, find_helper); + } + } + } if( find_helper.found ) { - if( find_helper.current_var->type == Var::TYPE_FUNCTION && find_helper.current_var->user_function ) + if( find_helper.result->type == Var::Type::TYPE_VOID && !find_helper.result->stream.empty() ) { - EvaluateFunction(find_helper.current_var->user_function, find_helper); + find_helper.result->type = Var::Type::TYPE_STREAM; } - else - if( find_helper.current_var->type == Var::TYPE_DATE && find_helper.current_var->date ) - { - // move me below (where TYPE_MODEL_CONTAINER_WRAPPER is used) - if( find_helper.is_last_field() ) - PrintDate(*find_helper.current_var->date, find_helper); - } - } - } - if( find_helper.found ) - { - if( find_helper.result->type == Var::Type::TYPE_VOID && !find_helper.result->stream.empty() ) + if( find_helper.previous_var && !result_child ) + { + // may only model_container_wrapper and space_wrapper here? + //find_helper.result->type == Var::TYPE_MODEL || + if( + find_helper.result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER || + 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); + } + } + + if( find_helper.result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER && find_helper.result->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( result_child ) + { + 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); + } + } + + find_helper.previous_var = find_helper.current_var; + find_helper.previous_result = find_helper.result; + } + else { - find_helper.result->type = Var::Type::TYPE_STREAM; + find_helper.previous_var = nullptr; + find_helper.previous_result = nullptr; } - - if( find_helper.result->type == Var::TYPE_MODEL_CONTAINER_WRAPPER && find_helper.result->model_container_wrapper ) - { - if( find_helper.is_last_field() && is_generating_for ) - { - find_helper.result->model_container_wrapper->increment_iterator(); - find_helper.result->clear_childs(); - - // 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( find_helper.previous_var && !result_child ) - { - // may only model_container_wrapper and space_wrapper here? - 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 || - find_helper.result->type == Var::TYPE_FUNCTION ) - { - result_child = find_helper.previous_var->add_child(name, *find_helper.result); - } - } - - if( result_child ) - { - 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); - } - } - - find_helper.previous_var = find_helper.current_var; - find_helper.previous_result = find_helper.result; - } - else - { - find_helper.previous_var = nullptr; - find_helper.previous_result = nullptr; } } @@ -1957,18 +2129,36 @@ bool Generator::EvaluateM { //find_helper.result->clear(); - morm::Model * model = find_helper.previous_result->model_container_wrapper->get_model(); + const std::wstring & cur_field = find_helper.current_name(); - if( model ) + // make a constant somewhere + if( cur_field == L"val" ) { - find_helper.found = CallModelField(*model, find_helper); + 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 { - // put some log (no [for] statement) - // CreateMsg(L"model ", name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); + // may cur_fiels is a global function, return true find_helper.found = false; - return false; + return true; } } @@ -2675,22 +2865,24 @@ void Generator::MakeTextF Call(item.function, nullptr, result, empty_stream); } - - if( result.type == Var::Type::TYPE_MODEL_CONTAINER_WRAPPER ) - { - if( !result.model_container_wrapper->is_iterator_correct() ) - break; - } - else - if( result.type == Var::Type::TYPE_SPACE_WRAPPER ) - { - if( !result.space_wrapper->get_last_for_loop_status() ) - break; - } - else - { + if( !result.to_bool() ) break; - } + +// if( result.type == Var::Type::TYPE_MODEL_CONTAINER_WRAPPER ) +// { +// if( !result.model_container_wrapper->is_iterator_correct() ) +// break; +// } +// else +// if( result.type == Var::Type::TYPE_SPACE_WRAPPER ) +// { +// if( !result.to_bool() ) +// break; +// } +// else +// { +// break; +// } if( !item.item_tab.empty() ) MakeText( *item.item_tab[0] ); // should be only one item diff --git a/src/var.h b/src/var.h index e4ddb07..deccca5 100644 --- a/src/var.h +++ b/src/var.h @@ -89,7 +89,9 @@ public: TYPE_MODEL, TYPE_MODEL_CONTAINER_WRAPPER, - TYPE_SPACE_WRAPPER, // or just type_space + + TYPE_SPACE_WRAPPER, + TYPE_SPACE, }; @@ -159,6 +161,7 @@ public: void set(std::list & model_container); void set(morm::SpaceWrapper & space_wrapper); + void set(pt::Space & space, bool create_wrapper = true); bool is_equal(const char * str) const; bool is_equal(const wchar_t * str) const; @@ -198,9 +201,9 @@ public: morm::ModelContainerWrapper * model_container_wrapper; pt::Date * date; morm::SpaceWrapper * space_wrapper; - pt::Space space_local; StreamType stream; + pt::Space * space; private: @@ -215,7 +218,7 @@ private: bool is_equal_bool(const wchar_t * str) const; bool is_equal_string(const wchar_t * str) const; - + void assert_type_stream(); /* @@ -273,6 +276,7 @@ void Var::copy(const Var & var) space_wrapper = var.space_wrapper; space_local = var.space_local; stream = var.stream; + space = var.space; if( model_container_wrapper ) { @@ -305,6 +309,7 @@ void Var::initialize_empty() model_container_wrapper = nullptr; date = nullptr; space_wrapper = nullptr; + space = nullptr; } @@ -412,6 +417,10 @@ bool Var::to_bool() const return space_wrapper->get_space()->to_bool(); break; + case TYPE_SPACE: + return space->to_bool(); + break; + case TYPE_MODEL_CONTAINER_WRAPPER: return !model_container_wrapper->is_container_empty(); break; @@ -685,6 +694,22 @@ void Var::set(morm::SpaceWrapper & space_wrapper) } +template +void Var::set(pt::Space & space, bool create_wrapper) +{ + clear(); + + if( create_wrapper ) + { + type = TYPE_SPACE_WRAPPER; + this->space_wrapper = new morm::SpaceWrapper(&space); + } + else + { + type = TYPE_SPACE; + this->space = &space; + } +} @@ -712,6 +737,7 @@ bool Var::is_equal(const char * str) const case TYPE_MODEL: case TYPE_MODEL_CONTAINER_WRAPPER: case TYPE_SPACE_WRAPPER: + case TYPE_SPACE: // IMPLEMENTME break; @@ -745,6 +771,7 @@ bool Var::is_equal(const wchar_t * str) const case TYPE_MODEL: case TYPE_MODEL_CONTAINER_WRAPPER: case TYPE_SPACE_WRAPPER: + case TYPE_SPACE: // IMPLEMENTME break; @@ -860,8 +887,26 @@ void Var::serialize_to(pt::WTextStream & str) case TYPE_FUNCTION: case TYPE_MODEL: case TYPE_MODEL_CONTAINER_WRAPPER: - case TYPE_SPACE_WRAPPER: break; + + case TYPE_SPACE_WRAPPER: + space_wrapper->get_space()->serialize_to_string(str); + break; + + case TYPE_SPACE: + space->serialize_to_string(str); + break; + } +} + + +template +void Var::assert_type_stream() +{ + if( type != TYPE_STREAM ) + { + clear(); + type = TYPE_STREAM; } } @@ -870,7 +915,7 @@ void Var::serialize_to(pt::WTextStream & str) template Var & Var::operator<<(const char * str) { - type = TYPE_STREAM; + assert_type_stream(); stream << str; return *this; } @@ -879,7 +924,7 @@ Var & Var::operator<<(const char * str) template Var & Var::operator<<(const wchar_t * str) { - type = TYPE_STREAM; + assert_type_stream(); stream << str; return *this; } @@ -888,7 +933,7 @@ Var & Var::operator<<(const wchar_t * str) template Var & Var::operator<<(const std::string & str) { - type = TYPE_STREAM; + assert_type_stream(); stream << str; return *this; } @@ -897,7 +942,7 @@ Var & Var::operator<<(const std::string & str) template Var & Var::operator<<(const std::wstring & str) { - type = TYPE_STREAM; + assert_type_stream(); stream << str; return *this; } @@ -906,7 +951,7 @@ Var & Var::operator<<(const std::wstring & str) template Var & Var::operator<<(char val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -914,7 +959,7 @@ Var & Var::operator<<(char val) template Var & Var::operator<<(unsigned char val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -922,7 +967,7 @@ Var & Var::operator<<(unsigned char val) template Var & Var::operator<<(wchar_t val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -930,7 +975,7 @@ Var & Var::operator<<(wchar_t val) template Var & Var::operator<<(bool val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -938,7 +983,7 @@ Var & Var::operator<<(bool val) template Var & Var::operator<<(short val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -946,7 +991,7 @@ Var & Var::operator<<(short val) template Var & Var::operator<<(int val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -954,7 +999,7 @@ Var & Var::operator<<(int val) template Var & Var::operator<<(long val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -962,7 +1007,7 @@ Var & Var::operator<<(long val) template Var & Var::operator<<(long long val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -970,7 +1015,7 @@ Var & Var::operator<<(long long val) template Var & Var::operator<<(unsigned short val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -978,7 +1023,7 @@ Var & Var::operator<<(unsigned short val) template Var & Var::operator<<(unsigned int val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -986,7 +1031,7 @@ Var & Var::operator<<(unsigned int val) template Var & Var::operator<<(unsigned long val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -994,7 +1039,7 @@ Var & Var::operator<<(unsigned long val) template Var & Var::operator<<(unsigned long long val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -1002,7 +1047,7 @@ Var & Var::operator<<(unsigned long long val) template Var & Var::operator<<(float val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -1010,7 +1055,7 @@ Var & Var::operator<<(float val) template Var & Var::operator<<(double val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -1018,7 +1063,7 @@ Var & Var::operator<<(double val) template Var & Var::operator<<(long double val) { - type = TYPE_STREAM; + assert_type_stream(); stream << val; return *this; } @@ -1026,7 +1071,7 @@ Var & Var::operator<<(long double val) template Var & Var::operator<<(const pt::Stream & str) { - type = TYPE_STREAM; + assert_type_stream(); stream << str; return *this; }