diff --git a/src/generator.h b/src/generator.h index ad734ad..640516a 100644 --- a/src/generator.h +++ b/src/generator.h @@ -147,7 +147,7 @@ private: Var * variable; #ifdef EZC_HAS_MORM_LIBRARY - morm::Wrapper * wrapper; + Var * wrapper; size_t field_index; #endif @@ -302,10 +302,10 @@ private: Var & result, std::vector> & parameters); - void PrintDate(pt::Date * date, Var & result, std::vector> & parameters); - bool PrintDatePart(pt::Date * date, const std::wstring & field, Var & result, std::vector> & parameters); + void PrintDate(pt::Date & date, std::vector> & parameters, Var & result); + //bool PrintDatePart(pt::Date & date, const std::wstring & field, std::vector> & parameters, Var & result); - bool CallDate(FindHelper & find_helper, std::vector & fields, Var & result, std::vector> & parameters); + //bool CallDate(pt::Date & date, const std::wstring & name, std::vector & fields, size_t & field_index, std::vector> & parameters, Var & result); void PrintLastSpaceField(pt::Space * space, Var & result, std::vector> & parameters); void CallSpaceObjectForLastField(Var & result, std::vector> & parameters, pt::Space * space); @@ -320,10 +320,11 @@ private: bool CallSpace(morm::SpaceWrapper * space_wrapper, const std::wstring & name, size_t & field_index, std::vector & fields, Var & result, std::vector> & parameters); #ifdef EZC_HAS_MORM_LIBRARY - bool CallModelField(morm::Model & model, const std::wstring & field, Var & result, std::vector> & parameters, const StreamType & in_stream); - bool CallModel(morm::Model & model, FindHelper & find_helper, std::vector & fields, Var & result, std::vector> & parameters, const StreamType & in_stream); - void FindLastModelWrapper(FindHelper & find_helper, std::vector & fields); - bool CallWrapper(FindHelper & find_helper, std::vector & fields, Var & result, std::vector> & parameters, const StreamType & in_stream); + bool CallModelField(morm::Model & model, const std::wstring & field, Var & result, std::vector> & parameters); +// bool CallModel(morm::Model & model, const std::wstring & name, std::vector & fields, size_t field_index, +// std::vector> & parameters, Var & result); +// void FindLastModelWrapper(FindHelper & find_helper, std::vector & fields); +// bool CallWrapper(FindHelper & find_helper, std::vector & fields, Var & result, std::vector> & parameters, const StreamType & in_stream); bool XXXRenameMe(Var & variable, std::vector & fields, size_t & field_index, Var & result, std::vector> & parameters, const StreamType & in_stream); @@ -1120,7 +1121,7 @@ void Generator::DumpModel template void Generator::PrintDate( - pt::Date * date, Var & result, std::vector> & parameters) + pt::Date & date, std::vector> & parameters, Var & result) { bool is_roman = HasParam(parameters, L"roman"); bool is_no_sec = HasParam(parameters, L"no_sec"); @@ -1130,7 +1131,7 @@ void Generator::PrintDate if( only_date ) { result.type = Var::TYPE_STREAM; - date->SerializeYearMonthDay(result.stream, is_roman); + date.SerializeYearMonthDay(result.stream, is_roman); } else if( only_time ) @@ -1138,21 +1139,26 @@ void Generator::PrintDate result.type = Var::TYPE_STREAM; if( is_no_sec ) - date->SerializeHourMin(result.stream); + date.SerializeHourMin(result.stream); else - date->SerializeHourMinSec(result.stream); + date.SerializeHourMinSec(result.stream); } else { result.type = Var::TYPE_STREAM; - date->Serialize(result.stream, is_roman, !is_no_sec); + date.Serialize(result.stream, is_roman, !is_no_sec); } } +/* + * these can be made as a simple function (e.g. from winix) + * as a first argument let they take pt::Date + */ +/* template bool Generator::PrintDatePart( - pt::Date * date, const std::wstring & field, Var & result, std::vector> & parameters) + pt::Date & date, const std::wstring & field, std::vector> & parameters, Var & result) { bool is_test = IsTestingFunctionExistence(); @@ -1161,7 +1167,7 @@ bool Generator::PrintDate if( !is_test ) { result.type = Var::TYPE_STREAM; - result.stream << date->year; + result.stream << date.year; } } else @@ -1173,9 +1179,9 @@ bool Generator::PrintDate result.type = Var::TYPE_STREAM; if( is_roman ) - pt::Date::SerializeMonthAsRoman(result.stream, date->month); + pt::Date::SerializeMonthAsRoman(result.stream, date.month); else - result.stream << date->month; + result.stream << date.month; } } else @@ -1184,7 +1190,7 @@ bool Generator::PrintDate if( !is_test ) { result.type = Var::TYPE_STREAM; - result.stream << date->day; + result.stream << date.day; } } else @@ -1193,7 +1199,7 @@ bool Generator::PrintDate if( !is_test ) { result.type = Var::TYPE_STREAM; - result.stream << date->hour; + result.stream << date.hour; } } else @@ -1202,7 +1208,7 @@ bool Generator::PrintDate if( !is_test ) { result.type = Var::TYPE_STREAM; - result.stream << date->min; + result.stream << date.min; } } else @@ -1211,7 +1217,7 @@ bool Generator::PrintDate if( !is_test ) { result.type = Var::TYPE_STREAM; - result.stream << date->sec; + result.stream << date.sec; } } else @@ -1221,45 +1227,41 @@ bool Generator::PrintDate return true; } +*/ +/* template bool Generator::CallDate( - FindHelper & find_helper, std::vector & fields, Var & result, std::vector> & parameters) + pt::Date & date, const std::wstring & name, std::vector & fields, size_t field_index, std::vector> & parameters, Var & result) { bool found = true; - bool all_fields_known = (find_helper.field_index == fields.size()); - bool last_field_not_known = (find_helper.field_index + 1 == fields.size()); + bool all_fields_known = (field_index == fields.size()); if( all_fields_known ) { - PrintDate(find_helper.wrapper->date, result, parameters); - } - else - if( last_field_not_known ) - { - if( !PrintDatePart(find_helper.wrapper->date, fields[find_helper.field_index], result, parameters) ) - { - if( !IsTestingFunctionExistence() ) - { - CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of date object"); - } - - found = false; - } + PrintDate(date, parameters, result); } else { - if( !IsTestingFunctionExistence() ) - { - CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", ", fields[find_helper.field_index].c_str(), L" is not a model nor a model container nor a space"); - } + found = PrintDatePart(date, fields[field_index], result, parameters); - found = false; +// if( found ) +// field_index += 1; + +// { +// if( !IsTestingFunctionExistence() ) +// { +// CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of date object"); +// } +// +// found = false; +// } } return found; } +*/ @@ -1488,7 +1490,7 @@ bool Generator::CallSpace template bool Generator::CallModelField( - morm::Model & model, const std::wstring & field, Var & result, std::vector> & parameters, const StreamType & in_stream) + morm::Model & model, const std::wstring & field, Var & result, std::vector> & parameters) { /* * if 'field' is a POD type then 'str' will be used in get_raw_value() @@ -1496,27 +1498,28 @@ bool Generator::CallModel * if 'field' is a getter method which takes Env<> then out_stream will be used and 'str' will be empty * */ - pt::WTextStream str; + //pt::WTextStream str; bool found = false; + StreamType fake_stream; - Env info(result, parameters, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); - found = model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false); + Env info(result, parameters, fake_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); + found = model.get_raw_value(nullptr, field.c_str(), nullptr, info); - if( found && !str.empty()) - { - bool no_escape = HasParam(parameters, L"raw", L"noescape"); - CopyStream(str, result.stream, !no_escape); - result.type = Var::TYPE_STREAM; - } +// if( found && !str.empty()) +// { +// bool no_escape = HasParam(parameters, L"raw", L"noescape"); +// CopyStream(str, result.stream, !no_escape); +// result.type = Var::TYPE_STREAM; +// } return found; } - +/* template bool Generator::CallModel( - morm::Model & model, FindHelper & find_helper, std::vector & fields, - Var & result, std::vector> & parameters, const StreamType & in_stream) + morm::Model & model, const std::wstring & name, std::vector & fields, size_t field_index, + std::vector> & parameters, Var & result) { bool found = true; @@ -1554,53 +1557,71 @@ bool Generator::CallModel return found; } +*/ - - +/* template void Generator::FindLastModelWrapper( - FindHelper & find_helper, std::vector & fields) + Var & var_parent, std::vector & fields, size_t & field_index) { - for(find_helper.field_index = 0 ; find_helper.field_index < fields.size() && find_helper.wrapper->has_model_object() ; ++find_helper.field_index) - { - std::wstring & field = fields[find_helper.field_index]; - morm::Wrapper * child_wrapper = find_helper.wrapper->find_child(field); + Var * var = &var_parent; - if( !child_wrapper ) + for( ; field_index < fields.size() && var->has_model_object() ; ++field_index) + { + std::wstring & field = fields[field_index]; + Var * child_var = var->find_child(field); + + if( !child_var ) { morm::Model * model = nullptr; - if( find_helper.wrapper->model ) + if( var->model ) { - model = find_helper.wrapper->model; + model = var->model; } else - if( find_helper.wrapper->model_container_wrapper ) + if( var->model_container_wrapper ) { - model = find_helper.wrapper->model_container_wrapper->get_model(); + model = var->model_container_wrapper->get_model(); // this can return null for lists/vectors in a case when the iterator is not pointing to a valid item } if( model ) { + // IMPROVE ME there'll be only one method to call a model morm::Wrapper new_wrapper = model->get_wrapper(nullptr, field.c_str()); if( new_wrapper.has_object() ) { - child_wrapper = find_helper.wrapper->add_child(field, new_wrapper); + Var child; + + if( new_wrapper.model ) + child.set(*new_wrapper.model); + + if( new_wrapper.model_container_wrapper ) + child.set(*new_wrapper.model_container_wrapper); + + if( new_wrapper.date ) + child.set(*new_wrapper.date); + + if( new_wrapper.space_wrapper ) + child.set(*new_wrapper.space_wrapper); + + child_var = var->add_child(field, new_wrapper); } + ////////////////////////////////////////////////////////////////////// } } - if( !child_wrapper ) + if( !child_var ) break; - find_helper.wrapper = child_wrapper; + var = child_var; } } +*/ - - +/* template bool Generator::CallWrapper( FindHelper & find_helper, std::vector & fields, @@ -1669,6 +1690,7 @@ bool Generator::CallWrapp return found; } +*/ #endif @@ -1867,22 +1889,43 @@ Var * Generator * var = FindInScope(*pname); + Var * old_var = var; + var = nullptr; + + if( field_index > 1 && old_var ) + { + var = old_var->find_child(*pname); + } + + if( !var ) + { + var = FindInScope(*pname); + } if( var ) { + /* + * fix me + * this is incorrect, as the parameters would be passed to the first function + * if the first function is a model we do not pass parameters to it, but to a field of the model (our next field) + * + */ if( was_evaluated ) { Var improve_me; - EvaluateVariable(*var, res, improve_me); + EvaluateVariable(name, *var, fields, field_index, res, improve_me); res[0] = improve_me; } else { - if( EvaluateVariable(*var, parameters, res[0]) ) + if( EvaluateVariable(name, *var, fields, field_index, parameters, res[0]) ) was_evaluated = true; } } + else + { + // log something + } field_index += 1; } @@ -1898,6 +1941,7 @@ bool Generator::EvaluateV { StreamType fake_stream; bool status = false; + bool all_fields_known = (field_index == fields.size()); if( var.type == Var::TYPE_FUNCTION ) { @@ -1916,7 +1960,7 @@ bool Generator::EvaluateV { if( var.model ) { - //status = CallModel(*var.model, name, fields, field_index, parameters, result); + status = CallModelField(*var.model, name, result, parameters); } else { @@ -1924,6 +1968,31 @@ bool Generator::EvaluateV } } + if( var.type == Var::TYPE_MODEL_CONTAINER_WRAPPER && var->model_container_wrapper ) + { + morm::Model * model = var.model_container_wrapper->get_model(); + + if( model ) + { + status = CallModelField(*model, name, result, parameters); + } + else + { + // can be printed even for [if-def...] + CreateMsg(L"model ", name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); + status = false; + } + + if( all_fields_known ) + { + if( is_generating_for ) + { + var.model_container_wrapper->increment_iterator(); + var.clear_childs(); + } + } + } + if( var.type == Var::TYPE_SPACE_WRAPPER ) { if( var.space_wrapper ) @@ -1936,6 +2005,12 @@ bool Generator::EvaluateV } } + if( var.type == Var::TYPE_DATE && var.date ) + { + if( all_fields_known ) + PrintDate(*var.date, parameters, result); + } + return status; } diff --git a/src/var.h b/src/var.h index 796fe12..d001ad8 100644 --- a/src/var.h +++ b/src/var.h @@ -42,6 +42,7 @@ #include "date/date.h" #include "modelcontainerwrapper.h" #include "textstream/textstream.h" +#include "morm.h" @@ -77,17 +78,28 @@ public: TYPE_FUNCTION, + TYPE_DATE, + TYPE_MODEL, TYPE_MODEL_CONTAINER_WRAPPER, TYPE_SPACE_WRAPPER, // or just type_space }; - Type type; Var(); + Var(const Var & var); + Var & operator=(const Var & var); + ~Var(); + // IMPROVEME add move cctor and operator= + + Var * add_child(const std::wstring & child_name, const Var & var); + Var * find_child(const std::wstring & child_name); + bool has_object(); + bool has_model_object(); void clear(); + void clear_childs(); bool to_bool() const; @@ -120,9 +132,12 @@ public: void set(UserFunction user_function); + void set(const pt::Date & date); + // this model is not copied, is it a correct interface? void set(morm::Model & model); + void set(morm::ModelContainerWrapper & model_container_wrapper); @@ -158,6 +173,8 @@ public: Var & operator<<(const pt::Stream & str); + + Type type; UserFunction user_function; morm::Model * model; morm::ModelContainerWrapper * model_container_wrapper; @@ -169,6 +186,11 @@ public: private: + std::map childs_map; + + void initialize_empty(); + void copy(const Var & var); + bool is_equal_bool(const char * str) const; bool is_equal_string(const char * str) const; @@ -199,25 +221,148 @@ private: template Var::Var() +{ + initialize_empty(); +} + + +template +Var::Var(const Var & var) +{ + initialize_empty(); + copy(var); +} + + +template +Var & Var::operator=(const Var & var) +{ + clear(); + copy(var); + + return *this; +} + + +template +void Var::copy(const Var & var) +{ + type = var.type; + user_function = var.user_function; + model = var.model; + model_container_wrapper = var.model_container_wrapper; + date = var.date; + space_wrapper = var.space_wrapper; + space_local = var.space_local; + stream = var.stream; + + if( model_container_wrapper ) + { + model_container_wrapper->increment_reference_counter(); + } + + if( space_wrapper ) + { + space_wrapper->increment_reference_counter(); + } + + // childs_map don't need to be copied +} + + + +template +Var::~Var() { clear(); } template -void Var::clear() +void Var::initialize_empty() { - //res = false; - //is_function = false; - type = TYPE_VOID; user_function = nullptr; model = nullptr; model_container_wrapper = nullptr; date = nullptr; space_wrapper = nullptr; +} + + +template +void Var::clear() +{ + if( model_container_wrapper ) + { + model_container_wrapper->decrement_reference_counter(); + + if( model_container_wrapper->get_reference_counter() == 0 && model_container_wrapper->should_be_auto_removed() ) + { + delete model_container_wrapper; + } + } + + if( space_wrapper ) + { + space_wrapper->decrement_reference_counter(); + + if( space_wrapper->get_reference_counter() == 0 && space_wrapper->should_be_auto_removed() ) + { + delete space_wrapper; + } + } + + initialize_empty(); space_local.clear(); stream.clear(); + clear_childs(); +} + + +template +void Var::clear_childs() +{ + childs_map.clear(); +} + + + +template +Var * Var::add_child(const std::wstring & child_name, const Var & var) +{ + Var & v = childs_map[child_name]; + v.clear(); + v = var; + return &v; +} + + +template +Var * Var::find_child(const std::wstring & child_name) +{ + auto i = childs_map.find(child_name); + + if( i != childs_map.end() ) + { + return &i->second; + } + + return nullptr; +} + + +template +bool Var::has_object() +{ + return type != TYPE_VOID; +} + + +template +bool Var::has_model_object() +{ + return model || model_container_wrapper; } @@ -238,6 +383,7 @@ bool Var::to_bool() const case TYPE_STREAM: case TYPE_FUNCTION: + case TYPE_DATE: case TYPE_MODEL: case TYPE_MODEL_CONTAINER_WRAPPER: case TYPE_SPACE_WRAPPER: @@ -413,6 +559,14 @@ void Var::set(UserFunction user_function) } +template +void Var::set(const pt::Date & date) +{ + type = TYPE_DATE; + this->date = &date; +} + + template void Var::set(morm::Model & model) { @@ -421,6 +575,14 @@ void Var::set(morm::Model & model) } +template +void Var::set(morm::ModelContainerWrapper & model_container_wrapper) +{ + type = TYPE_MODEL_CONTAINER_WRAPPER; + this->model_container_wrapper = &model_container_wrapper; +} + + template bool Var::is_equal(const char * str) const @@ -438,6 +600,7 @@ bool Var::is_equal(const char * str) const case TYPE_DOUBLE: case TYPE_STREAM: case TYPE_FUNCTION: + case TYPE_DATE: case TYPE_MODEL: case TYPE_MODEL_CONTAINER_WRAPPER: case TYPE_SPACE_WRAPPER: @@ -465,6 +628,7 @@ bool Var::is_equal(const wchar_t * str) const case TYPE_DOUBLE: case TYPE_STREAM: case TYPE_FUNCTION: + case TYPE_DATE: case TYPE_MODEL: case TYPE_MODEL_CONTAINER_WRAPPER: case TYPE_SPACE_WRAPPER: @@ -573,6 +737,10 @@ void Var::serialize_to(pt::WTextStream & str) str = stream; break; + case TYPE_DATE: + date->SerializeISO(str); + break; + case TYPE_VOID: case TYPE_FUNCTION: case TYPE_MODEL: