add two new ezc statements: [if-def ...] and [if-not-def ...]

[if-def my_function] returns true if my_function is defined somewhere (either a model, model container, space, date, block, function or variable)
add support for "noescape" or "raw" parameters to Space fields
fixed: CallWrapper() didn't return a status if a model/space/date/container was found
This commit is contained in:
Tomasz Sowa 2021-07-02 20:23:20 +02:00
parent 849b3e9ecc
commit 995cccdace
5 changed files with 333 additions and 128 deletions

View File

@ -172,9 +172,14 @@ struct FunInfo
bool is_for; bool is_for;
// indicates that this function is from [if ...] statement // indicates that this function is from [if ...] statement
// it is true for all kind of if's: if-one, if-any, if-no....
bool is_if; bool is_if;
// indicates that this function is from [if-def ...] statement
bool is_if_def;
// indicates that this function is from [if-not-def ...] statement
bool is_if_not_def;
// indicates that this funcion is a normal statement e.g.: [funcion_name] // indicates that this funcion is a normal statement e.g.: [funcion_name]
bool is_normal; bool is_normal;
@ -221,6 +226,8 @@ struct FunInfo
res = false; // result is false by default res = false; // result is false by default
is_for = false; is_for = false;
is_if = false; is_if = false;
is_if_def = false;
is_if_not_def = false;
is_normal = false; is_normal = false;
is_filter = false; is_filter = false;
iter = 0; iter = 0;

View File

@ -242,6 +242,8 @@ private:
// true if the Generator is working with [for ...], [if ...] etc. // true if the Generator is working with [for ...], [if ...] etc.
bool is_generating_for; bool is_generating_for;
bool is_generating_if; bool is_generating_if;
bool is_generating_if_def;
bool is_generating_if_not_def;
bool is_generating_normal; bool is_generating_normal;
bool is_generating_filter; bool is_generating_filter;
@ -259,7 +261,6 @@ private:
ExpressionParser * expression_parser; ExpressionParser * expression_parser;
void ResizeStreamStack(std::vector<StreamType*> & stream_tab, size_t stream_tab_max_size); void ResizeStreamStack(std::vector<StreamType*> & stream_tab, size_t stream_tab_max_size);
void ResizeFilterTab(); void ResizeFilterTab();
void ResizeStack(); void ResizeStack();
@ -285,6 +286,7 @@ private:
template<class CharType> template<class CharType>
CharType ToLower(CharType c); CharType ToLower(CharType c);
bool IsTestingFunctionExistence();
bool CheckBlockArgument(int arg_index, FindHelper & find_helper); bool CheckBlockArgument(int arg_index, FindHelper & find_helper);
@ -295,11 +297,11 @@ private:
#endif #endif
bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper); bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper);
bool FindInVariables(const std::wstring & name, FindHelper & find_helper); bool FindInVariables(const std::wstring & name, FindHelper & find_helper);
bool Find(Item::Function & item_fun, FindHelper & find_helper); bool Find(Item::Function & item_fun, FindHelper & find_helper);
void PrepareEnvStruct(FunInfo<StreamType> & info);
void CallFunction(typename Functions<StreamType>::UserFunction & function, FunInfo<StreamType> & info); void CallFunction(typename Functions<StreamType>::UserFunction & function, FunInfo<StreamType> & info);
void CallFunction(typename Functions<StreamType>::UserFunction & function, void CallFunction(typename Functions<StreamType>::UserFunction & function,
@ -316,8 +318,10 @@ private:
void PrintDate(pt::Date * date, std::vector<Var> parameters, StreamType & out_stream); void PrintDate(pt::Date * date, std::vector<Var> parameters, StreamType & out_stream);
bool PrintDatePart(pt::Date * date, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream); bool PrintDatePart(pt::Date * date, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream);
void CallSpaceObjectForLastField(std::vector<Var> & parameters, StreamType & out_stream, pt::Space * space); bool CallDate(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream);
void PrintLastSpaceField(pt::Space * space, std::vector<Var> & parameters, StreamType & out_stream);
void CallSpaceObjectForLastField(std::vector<Var> & parameters, StreamType & out_stream, pt::Space * space);
pt::Space * CallSpaceObjectForMiddleField(std::wstring & root_space_name, std::vector<std::wstring> & fields, size_t field_index, pt::Space * space); pt::Space * CallSpaceObjectForMiddleField(std::wstring & root_space_name, std::vector<std::wstring> & fields, size_t field_index, pt::Space * space);
void CallSpaceTableForLastField(morm::SpaceWrapper & space_wrapper, std::vector<Var> & parameters, StreamType & out_stream, void CallSpaceTableForLastField(morm::SpaceWrapper & space_wrapper, std::vector<Var> & parameters, StreamType & out_stream,
@ -326,13 +330,13 @@ private:
pt::Space * CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector<std::wstring> & fields, pt::Space * CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector<std::wstring> & fields,
size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index); size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index);
void CallSpace(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> & parameters, StreamType & out_stream); bool CallSpace(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> & parameters, StreamType & out_stream);
#ifdef EZC_HAS_MORM_LIBRARY #ifdef EZC_HAS_MORM_LIBRARY
bool CallModelField(morm::Model & model, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream); bool CallModelField(morm::Model & model, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream);
void CallModel(morm::Model & model, FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream); bool CallModel(morm::Model & model, FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream);
void FindLastModelWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields); void FindLastModelWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields);
void CallWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream); bool CallWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream);
#endif #endif
void CallObject(BaseObj<StreamType> & base_obj, void CallObject(BaseObj<StreamType> & base_obj,
@ -392,6 +396,8 @@ private:
void MakeTextIf_go(Item & item, bool result); void MakeTextIf_go(Item & item, bool result);
void MakeTextIf(Item & item); void MakeTextIf(Item & item);
void MakeTextIfDef(Item & item);
void MakeTextIfNotDef(Item & item);
void MakeTextFor(Item & item); void MakeTextFor(Item & item);
void MakeItemText(Item & item); void MakeItemText(Item & item);
void MakeTextContainer(Item & item); void MakeTextContainer(Item & item);
@ -677,8 +683,6 @@ void Generator<StreamType>::ResizeBlockStack()
template<class StreamType> template<class StreamType>
void Generator<StreamType>::ClearStreamStack(std::vector<StreamType*> & stream_tab) void Generator<StreamType>::ClearStreamStack(std::vector<StreamType*> & stream_tab)
{ {
@ -956,6 +960,12 @@ void Generator<StreamType>::Generate(OutStreams<StreamType> & out_streams)
} }
template<class StreamType>
bool Generator<StreamType>::IsTestingFunctionExistence()
{
return is_generating_if_def || is_generating_if_not_def;
}
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::CheckBlockArgument(int arg_index, FindHelper & find_helper) bool Generator<StreamType>::CheckBlockArgument(int arg_index, FindHelper & find_helper)
@ -1102,7 +1112,7 @@ bool Generator<StreamType>::Find(Item::Function & item_fun, FindHelper & find_he
if( FindInModels(find_helper) ) if( FindInModels(find_helper) )
return true; return true;
if( !item_fun.fields.empty() ) if( !item_fun.fields.empty() && !IsTestingFunctionExistence() )
{ {
CreateMsg(L"unknown model", find_helper.fun_name->c_str()); CreateMsg(L"unknown model", find_helper.fun_name->c_str());
return false; return false;
@ -1122,27 +1132,36 @@ bool Generator<StreamType>::Find(Item::Function & item_fun, FindHelper & find_he
if( FindInVariables(*find_helper.fun_name, find_helper) ) if( FindInVariables(*find_helper.fun_name, find_helper) )
return true; return true;
CreateMsg(L"unknown function", find_helper.fun_name->c_str()); if( !IsTestingFunctionExistence() )
CreateMsg(L"unknown function", find_helper.fun_name->c_str());
return false; return false;
} }
template<class StreamType>
void Generator<StreamType>::PrepareEnvStruct(FunInfo<StreamType> & info)
{
info.Clear();
info.is_for = is_generating_for;
info.is_if = is_generating_if;
info.is_if_def = is_generating_if_def;
info.is_if_not_def = is_generating_if_not_def;
info.is_normal = is_generating_normal;
info.is_filter = is_generating_filter;
info.iter = info.stack.iter;
info.stack_tab = stack_tab.data();
info.stack_index = stack_index-1;
}
template<class StreamType> template<class StreamType>
void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFunction & function, FunInfo<StreamType> & info) void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFunction & function, FunInfo<StreamType> & info)
{ {
info.Clear(); PrepareEnvStruct(info);
info.is_for = is_generating_for;
info.is_if = is_generating_if;
info.is_normal = is_generating_normal;
info.is_filter = is_generating_filter;
info.iter = info.stack.iter;
info.stack_tab = stack_tab.data();
info.stack_index = stack_index-1;
(function)(info); (function)(info);
last_res = info.res; last_res = info.res;
} }
@ -1154,39 +1173,29 @@ void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFun
StreamType & out_stream, StreamType & out_stream,
const StreamType & in_stream) const StreamType & in_stream)
{ {
if( parameters.empty() ) if( !IsTestingFunctionExistence() )
{ {
FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); if( parameters.empty() )
CallFunction(function, info); {
} FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
else CallFunction(function, info);
{ }
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); else
CallFunction(function, info); {
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
CallFunction(function, info);
}
} }
} }
template<class StreamType> template<class StreamType>
void Generator<StreamType>::CallObject(BaseObj<StreamType> & base_obj, int method_index, FunInfo<StreamType> & info) void Generator<StreamType>::CallObject(BaseObj<StreamType> & base_obj, int method_index, FunInfo<StreamType> & info)
{ {
info.Clear(); PrepareEnvStruct(info);
info.is_for = is_generating_for;
info.is_if = is_generating_if;
info.is_normal = is_generating_normal;
info.is_filter = is_generating_filter;
info.iter = info.stack.iter;
info.stack_tab = stack_tab.data();
info.stack_index = stack_index-1;
base_obj.CallFun(method_index, info); base_obj.CallFun(method_index, info);
last_res = info.res; last_res = info.res;
} }
@ -1306,35 +1315,100 @@ void Generator<StreamType>::PrintDate(pt::Date * date, std::vector<Var> paramete
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::PrintDatePart(pt::Date * date, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream) bool Generator<StreamType>::PrintDatePart(pt::Date * date, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream)
{ {
bool is_test = IsTestingFunctionExistence();
if( field == L"year" ) if( field == L"year" )
out_stream << date->year; {
if( !is_test )
out_stream << date->year;
}
else else
if( field == L"month" ) if( field == L"month" )
out_stream << date->month; {
if( !is_test )
out_stream << date->month;
}
else else
if( field == L"day" ) if( field == L"day" )
out_stream << date->day; {
if( !is_test )
out_stream << date->day;
}
else else
if( field == L"hour" ) if( field == L"hour" )
out_stream << date->hour; {
if( !is_test )
out_stream << date->hour;
}
else else
if( field == L"min" ) if( field == L"min" )
out_stream << date->min; {
if( !is_test )
out_stream << date->min;
}
else else
if( field == L"sec" ) if( field == L"sec" )
out_stream << date->sec; {
if( !is_test )
out_stream << date->sec;
}
else else
{
return false; return false;
}
return true; return true;
} }
template<class StreamType>
bool Generator<StreamType>::CallDate(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream)
{
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());
if( all_fields_known )
{
PrintDate(find_helper.wrapper->date, parameters, out_stream);
}
else
if( last_field_not_known )
{
if( !PrintDatePart(find_helper.wrapper->date, fields[find_helper.field_index], parameters, out_stream) )
{
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;
}
}
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 = false;
}
return found;
}
template<class StreamType> template<class StreamType>
void Generator<StreamType>::CallSpaceObjectForLastField(std::vector<Var> & parameters, StreamType & out_stream, pt::Space * space) void Generator<StreamType>::CallSpaceObjectForLastField(std::vector<Var> & parameters, StreamType & out_stream, pt::Space * space)
{ {
// CHECKME should we convert the last value to last_res? if( !IsTestingFunctionExistence() )
DumpSpaceIfNeeded(parameters, out_stream, space); {
// CHECKME should we convert the last value to last_res?
DumpSpaceIfNeeded(parameters, out_stream, space);
}
} }
@ -1344,7 +1418,7 @@ pt::Space * Generator<StreamType>::CallSpaceObjectForMiddleField(std::wstring &
std::wstring & next_field = fields[field_index]; std::wstring & next_field = fields[field_index];
space = space->get_space(next_field); space = space->get_space(next_field);
if( !space ) if( !space && !IsTestingFunctionExistence() )
{ {
CreateMsg(L"cannot find space field: ", root_space_name, fields, field_index + 1); CreateMsg(L"cannot find space field: ", root_space_name, fields, field_index + 1);
} }
@ -1360,7 +1434,7 @@ void Generator<StreamType>::CallSpaceTableForLastField(morm::SpaceWrapper & spac
{ {
pt::Space::TableType * table = space->get_table(); pt::Space::TableType * table = space->get_table();
if( stack_tab[stack_index-1].is_for ) if( is_generating_for )
{ {
// we are in [for...]statement, increment iterator and check the range // we are in [for...]statement, increment iterator and check the range
space_wrapper.increment_iterator(model_wrapper_space_table_index, table->size()); space_wrapper.increment_iterator(model_wrapper_space_table_index, table->size());
@ -1370,23 +1444,27 @@ void Generator<StreamType>::CallSpaceTableForLastField(morm::SpaceWrapper & spac
else else
{ {
// we are not in [for..], it can be for example [if...], return true if the table is not empty // we are not in [for..], it can be for example [if...], return true if the table is not empty
// if we are in [if-def...] - then last_res is set later in MakeTextIfDef(Item & item) when Call() method returns
last_res = !table->empty(); last_res = !table->empty();
} }
DumpSpaceIfNeeded(parameters, out_stream, space); if( !IsTestingFunctionExistence() )
if( IsCurrentParam(parameters) )
{ {
size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); DumpSpaceIfNeeded(parameters, out_stream, space);
if( iterator_value < table->size() ) if( IsCurrentParam(parameters) )
{ {
(*table)[iterator_value]->serialize_to_string(out_stream); size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index);
if( iterator_value < table->size() )
{
(*table)[iterator_value]->serialize_to_string(out_stream);
}
} }
} }
} }
template<class StreamType> template<class StreamType>
pt::Space * Generator<StreamType>::CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector<std::wstring> & fields, pt::Space * Generator<StreamType>::CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector<std::wstring> & fields,
size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index) size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index)
@ -1402,6 +1480,7 @@ pt::Space * Generator<StreamType>::CallSpaceTableForMiddleField(morm::SpaceWrapp
} }
else else
{ {
// this message can be print even for [if-def...]
CreateMsg(L"space table: ", root_space_name, fields, field_index, L" is not initialized, have you forgotten to use [for...] statement?"); CreateMsg(L"space table: ", root_space_name, fields, field_index, L" is not initialized, have you forgotten to use [for...] statement?");
space = nullptr; space = nullptr;
} }
@ -1411,7 +1490,26 @@ pt::Space * Generator<StreamType>::CallSpaceTableForMiddleField(morm::SpaceWrapp
template<class StreamType> template<class StreamType>
void Generator<StreamType>::CallSpace(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> & parameters, StreamType & out_stream) void Generator<StreamType>::PrintLastSpaceField(pt::Space * space, std::vector<Var> & parameters, StreamType & out_stream)
{
bool no_escape = HasParam(parameters, L"raw", L"noescape");
if( no_escape )
{
pt::WTextStream str;
space->serialize_to_string(str);
CopyStream(str, out_stream, false);
}
else
{
space->serialize_to_string(out_stream);
}
}
template<class StreamType>
bool Generator<StreamType>::CallSpace(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> & parameters, StreamType & out_stream)
{ {
morm::SpaceWrapper * space_wrapper = find_helper.wrapper->space_wrapper; morm::SpaceWrapper * space_wrapper = find_helper.wrapper->space_wrapper;
pt::Space * space = space_wrapper->get_space(); pt::Space * space = space_wrapper->get_space();
@ -1463,23 +1561,33 @@ void Generator<StreamType>::CallSpace(FindHelper & find_helper, std::vector<std:
else else
{ {
CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" exceeded the maximum number of fields for a space object"); CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" exceeded the maximum number of fields for a space object");
break; space = nullptr;
} }
} }
else else
{ {
if( is_last_field ) if( is_last_field )
{ {
space->serialize_to_string(out_stream); if( !IsTestingFunctionExistence() )
{
PrintLastSpaceField(space, parameters, out_stream);
}
field_index += 1; field_index += 1;
} }
else else
{ {
CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" is not a model, model container nor a space"); if( !IsTestingFunctionExistence() )
break; {
CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" of a space is not an object nor a table");
}
space = nullptr;
} }
} }
} }
return space != nullptr;
} }
@ -1513,8 +1621,8 @@ bool Generator<StreamType>::CallModelField(morm::Model & model, const std::wstri
if( found && !str.empty()) if( found && !str.empty())
{ {
bool should_escape = HasParam(parameters, L"raw", L"noescape"); bool no_escape = HasParam(parameters, L"raw", L"noescape");
CopyStream(str, out_stream, should_escape); CopyStream(str, out_stream, !no_escape);
} }
return found; return found;
@ -1522,13 +1630,18 @@ bool Generator<StreamType>::CallModelField(morm::Model & model, const std::wstri
template<class StreamType> template<class StreamType>
void Generator<StreamType>::CallModel(morm::Model & model, FindHelper & find_helper, std::vector<std::wstring> & fields, bool Generator<StreamType>::CallModel(morm::Model & model, FindHelper & find_helper, std::vector<std::wstring> & fields,
std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream) std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream)
{ {
bool found = true;
if( find_helper.field_index == fields.size() ) if( find_helper.field_index == fields.size() )
{ {
// all fields items are models or models containers // all fields items are models or models containers
DumpModelIfNeeded(model, parameters, out_stream); if( !IsTestingFunctionExistence() )
{
DumpModelIfNeeded(model, parameters, out_stream);
}
} }
else else
if( find_helper.field_index + 1 == fields.size() ) if( find_helper.field_index + 1 == fields.size() )
@ -1536,13 +1649,25 @@ void Generator<StreamType>::CallModel(morm::Model & model, FindHelper & find_hel
// last field is not a model nor a models container // last field is not a model nor a models container
if( !CallModelField(model, fields[find_helper.field_index], parameters, out_stream, in_stream) ) if( !CallModelField(model, fields[find_helper.field_index], parameters, out_stream, in_stream) )
{ {
CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of a model object"); if( !IsTestingFunctionExistence() )
{
CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of a model object");
}
found = false;
} }
} }
else else
{ {
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"); 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 = false;
} }
return found;
} }
@ -1590,9 +1715,10 @@ void Generator<StreamType>::FindLastModelWrapper(FindHelper & find_helper, std::
template<class StreamType> template<class StreamType>
void Generator<StreamType>::CallWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields, bool Generator<StreamType>::CallWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields,
std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream) std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream)
{ {
bool found = true;
last_res = false; last_res = false;
FindLastModelWrapper(find_helper, fields); FindLastModelWrapper(find_helper, fields);
@ -1606,33 +1732,17 @@ void Generator<StreamType>::CallWrapper(FindHelper & find_helper, std::vector<st
if( find_helper.wrapper->space_wrapper ) if( find_helper.wrapper->space_wrapper )
{ {
CallSpace(find_helper, fields, parameters, out_stream); found = CallSpace(find_helper, fields, parameters, out_stream);
} }
if( find_helper.wrapper->date ) if( find_helper.wrapper->date )
{ {
if( all_fields_known ) found = CallDate(find_helper, fields, parameters, out_stream);
{
PrintDate(find_helper.wrapper->date, parameters, out_stream);
}
else
if( last_field_not_known )
{
// last field is not a model nor a models container
if( !PrintDatePart(find_helper.wrapper->date, fields[find_helper.field_index], parameters, out_stream) )
{
CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of date object");
}
}
else
{
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");
}
} }
if( find_helper.wrapper->model ) if( find_helper.wrapper->model )
{ {
CallModel(*find_helper.wrapper->model, find_helper, fields, parameters, out_stream, in_stream); found = CallModel(*find_helper.wrapper->model, find_helper, fields, parameters, out_stream, in_stream);
} }
if( find_helper.wrapper->model_container_wrapper ) if( find_helper.wrapper->model_container_wrapper )
@ -1641,19 +1751,21 @@ void Generator<StreamType>::CallWrapper(FindHelper & find_helper, std::vector<st
if( model ) if( model )
{ {
CallModel(*model, find_helper, fields, parameters, out_stream, in_stream); found = CallModel(*model, find_helper, fields, parameters, out_stream, in_stream);
} }
else else
{ {
if( last_field_not_known ) if( last_field_not_known )
{ {
// can be printed even for [if-def...]
CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?");
found = false;
} }
} }
if( all_fields_known ) if( all_fields_known )
{ {
if( stack_tab[stack_index-1].is_for ) if( is_generating_for )
{ {
find_helper.wrapper->model_container_wrapper->increment_iterator(); find_helper.wrapper->model_container_wrapper->increment_iterator();
find_helper.wrapper->clear_childs(); find_helper.wrapper->clear_childs();
@ -1661,10 +1773,13 @@ void Generator<StreamType>::CallWrapper(FindHelper & find_helper, std::vector<st
} }
else else
{ {
// for [if-def...] last_res will be set later
last_res = !find_helper.wrapper->model_container_wrapper->is_container_empty(); last_res = !find_helper.wrapper->model_container_wrapper->is_container_empty();
} }
} }
} }
return found;
} }
#endif #endif
@ -1678,15 +1793,18 @@ void Generator<StreamType>::CallObject(BaseObj<StreamType> & base_obj,
StreamType & out_stream, StreamType & out_stream,
const StreamType & in_stream) const StreamType & in_stream)
{ {
if( parameters.empty() ) if( !IsTestingFunctionExistence() )
{ {
FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); if( parameters.empty() )
CallObject(base_obj, method_index, info); {
} FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
else CallObject(base_obj, method_index, info);
{ }
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); else
CallObject(base_obj, method_index, info); {
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
CallObject(base_obj, method_index, info);
}
} }
} }
@ -1703,24 +1821,27 @@ bool Generator<StreamType>::CallBlock(Item & item_block,
return false; return false;
} }
StreamType * old_stream = output_stream; if( !IsTestingFunctionExistence() )
BlockStack & block_stack = block_stack_tab[block_stack_index]; {
StreamType * old_stream = output_stream;
BlockStack & block_stack = block_stack_tab[block_stack_index];
block_stack.was_return = false; block_stack.was_return = false;
block_stack.args = parameters; block_stack.args = parameters;
output_stream = block_stack.out_stream; output_stream = block_stack.out_stream;
ClearStream(*output_stream); ClearStream(*output_stream);
block_stack_index += 1; block_stack_index += 1;
MakeText(item_block); MakeText(item_block);
CopyStream(*output_stream, out_stream); CopyStream(*output_stream, out_stream);
// last_res is set by [return ...] statement or other last evaluated function // last_res is set by [return ...] statement or other last evaluated function
ClearStream(*output_stream); ClearStream(*output_stream);
output_stream = old_stream; output_stream = old_stream;
block_stack_index -= 1; block_stack_index -= 1;
}
return true; return true;
} }
@ -1736,8 +1857,12 @@ bool Generator<StreamType>::CallVariable(Item::Function & item_fun, Var & variab
} }
else else
{ {
out_stream << variable.str; if( !IsTestingFunctionExistence() )
last_res = variable.res; {
out_stream << variable.str;
last_res = variable.res;
}
return true; return true;
} }
} }
@ -1793,7 +1918,7 @@ std::vector<Var> parameters;
#ifdef EZC_HAS_MORM_LIBRARY #ifdef EZC_HAS_MORM_LIBRARY
if( find_helper.wrapper ) if( find_helper.wrapper )
CallWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream); return CallWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream);
else else
#endif #endif
if( find_helper.base_obj ) if( find_helper.base_obj )
@ -2250,6 +2375,42 @@ void Generator<StreamType>::MakeTextIf(Item & item)
} }
template<class StreamType>
void Generator<StreamType>::MakeTextIfDef(Item & item)
{
is_generating_if_def = true;
if( program_mode )
{
//CHECKME
//EvaluateProgramNode(item);
}
else
{
last_res = Call(item.function);
}
MakeTextIf_go(item, last_res);
}
template<class StreamType>
void Generator<StreamType>::MakeTextIfNotDef(Item & item)
{
is_generating_if_not_def = true;
if( program_mode )
{
//CHECKME
//EvaluateProgramNode(item);
}
else
{
last_res = !Call(item.function);
}
MakeTextIf_go(item, last_res);
}
template<class StreamType> template<class StreamType>
@ -2598,12 +2759,14 @@ void Generator<StreamType>::MakeText(Item & item)
if( LimitAchieved() ) if( LimitAchieved() )
return; return;
current_item += 1; current_item += 1;
stack_index += 1; stack_index += 1;
is_generating_for = false; is_generating_for = false;
is_generating_if = false; is_generating_if = false;
is_generating_normal = false; is_generating_if_def = false;
is_generating_filter = false; is_generating_if_not_def = false;
is_generating_normal = false;
is_generating_filter = false;
stack_tab[stack_index-1].Clear(); stack_tab[stack_index-1].Clear();
stack_tab[stack_index-1].item = &item; stack_tab[stack_index-1].item = &item;
@ -2612,6 +2775,8 @@ void Generator<StreamType>::MakeText(Item & item)
else if( item.type == Item::item_container ) MakeTextContainer(item); else if( item.type == Item::item_container ) MakeTextContainer(item);
else if( item.type == Item::item_function ) MakeTextFunction(item); else if( item.type == Item::item_function ) MakeTextFunction(item);
else if( item.type == Item::item_if ) MakeTextIf(item); else if( item.type == Item::item_if ) MakeTextIf(item);
else if( item.type == Item::item_if_def ) MakeTextIfDef(item);
else if( item.type == Item::item_if_not_def ) MakeTextIfNotDef(item);
else if( item.type == Item::item_def ) MakeTextDefine(item); else if( item.type == Item::item_def ) MakeTextDefine(item);
else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item); else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item);
else if( item.type == Item::item_let ) MakeTextLet(item); else if( item.type == Item::item_let ) MakeTextLet(item);

View File

@ -53,7 +53,7 @@ struct Item
{ {
enum Type enum Type
{ {
item_none, item_container, item_text, item_function, item_if, item_none, item_container, item_text, item_function, item_if, item_if_def, item_if_not_def,
item_for, item_else, item_end, item_err, item_include, item_comment, item_for, item_else, item_end, item_err, item_include, item_comment,
item_def, item_def_if_not_set, item_let, item_let_if_not_set, item_def, item_def_if_not_set, item_let, item_let_if_not_set,
item_filter, item_ezc, item_block, item_return item_filter, item_ezc, item_block, item_return

View File

@ -745,6 +745,35 @@ void PatternParser::ReadDirectiveIf(Item & item)
} }
void PatternParser::ReadDirectiveIfDef(Item & item)
{
item.type = Item::item_if_def;
if( ReadFunction(item) )
{
if( !item.function.is_function || item.function.parameters.size() > 0 )
{
item.type = Item::item_err;
item.function.Clear();
}
}
}
void PatternParser::ReadDirectiveIfNotDef(Item & item)
{
item.type = Item::item_if_not_def;
if( ReadFunction(item) )
{
if( !item.function.is_function || item.function.parameters.size() > 0 )
{
item.type = Item::item_err;
item.function.Clear();
}
}
}
void PatternParser::ReadDirectiveEnd(Item & item) void PatternParser::ReadDirectiveEnd(Item & item)
{ {
@ -991,6 +1020,8 @@ std::wstring name;
ReadName(name); ReadName(name);
if ( name == L"if" ) ReadDirectiveIf(item); if ( name == L"if" ) ReadDirectiveIf(item);
else if( name == L"if-def" ) ReadDirectiveIfDef(item);
else if( name == L"if-not-def" )ReadDirectiveIfNotDef(item);
else if( name == L"end" ) ReadDirectiveEnd(item); else if( name == L"end" ) ReadDirectiveEnd(item);
else if( name == L"else" ) ReadDirectiveElse(item); else if( name == L"else" ) ReadDirectiveElse(item);
else if( name == L"for" ) ReadDirectiveFor(item); else if( name == L"for" ) ReadDirectiveFor(item);
@ -1325,7 +1356,7 @@ bool PatternParser::CreateTree(Item & item)
if( item.type == Item::item_container ) if( item.type == Item::item_container )
CreateTreeContainer(item); CreateTreeContainer(item);
if( item.type == Item::item_if ) if( item.type == Item::item_if || item.type == Item::item_if_def || item.type == Item::item_if_not_def )
CreateTreeReadIf(item); // reads one child or two if [else] statement is present CreateTreeReadIf(item); // reads one child or two if [else] statement is present
if( item.type == Item::item_for || if( item.type == Item::item_for ||

View File

@ -176,6 +176,8 @@ private:
bool ReadFunction(Item & item); bool ReadFunction(Item & item);
void ReadDirectiveIf(Item & item); void ReadDirectiveIf(Item & item);
void ReadDirectiveIfDef(Item & item);
void ReadDirectiveIfNotDef(Item & item);
void ReadDirectiveEnd(Item & item); void ReadDirectiveEnd(Item & item);
void ReadDirectiveElse(Item & item); void ReadDirectiveElse(Item & item);
void ReadDirectiveFor(Item & item); void ReadDirectiveFor(Item & item);