some work on iterating through tables

This commit is contained in:
Tomasz Sowa 2021-11-24 13:19:27 +01:00
parent 86d0b7d886
commit 973f05cc08
2 changed files with 125 additions and 109 deletions

View File

@ -203,16 +203,27 @@ private:
previous_result = nullptr; previous_result = nullptr;
} }
// rename me to current_field()
const std::wstring & current_name() const std::wstring & current_name()
{ {
return (field_index == 0)? name : fields[field_index - 1]; return (field_index == 0)? name : fields[field_index - 1];
} }
const std::wstring & next_field()
{
return fields[field_index];
}
bool is_last_field() bool is_last_field()
{ {
return field_index == fields.size(); return field_index == fields.size();
} }
bool is_next_field()
{
return field_index < fields.size();
}
}; };
struct BlockStack 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); 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); bool CallSpace(pt::Space & root_space, FindHelper & find_helper);
@ -377,7 +388,8 @@ private:
void FindVariable(FindHelper & find_helper); void FindVariable(FindHelper & find_helper);
void EvaluateVariable(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<StreamType>::UserFunction user_function, FindHelper & find_helper); void EvaluateFunction(typename Var<StreamType>::UserFunction user_function, FindHelper & find_helper);
@ -1428,18 +1440,18 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintLast
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream> template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallSpace( bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallSpaceWrapper(
morm::SpaceWrapper & space_wrapper, FindHelper & find_helper) morm::SpaceWrapper & space_wrapper, FindHelper & find_helper)
{ {
pt::Space * space = space_wrapper.get_space(); pt::Space * space = space_wrapper.get_space();
size_t model_wrapper_space_table_index = 0; 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() ) while( find_helper.is_next_field() )
{ {
if( space->is_object() ) 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); pt::Space * next_space = space->get_space(next_field);
if( next_space ) if( next_space )
@ -1459,7 +1471,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallSpace
{ {
if( model_wrapper_space_table_index < space_wrapper.space_indices_table_size() ) 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" ) if( next_field == L"first" )
{ {
@ -1499,7 +1511,9 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallSpace
if( !next_space ) if( !next_space )
{ {
// a [for ...] was not used beforehand // 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<StreamType, is_pikotools_stream, is_autoescape_stream>::CallSpace
else else
if( space->is_table() ) if( space->is_table() )
{ {
CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message //CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message
return false; //return false;
find_helper.result->set(*space, false);
return true;
} }
else else
{ {
@ -1623,8 +1639,10 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallSpace
if( space->is_table() ) if( space->is_table() )
{ {
CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message // CreateMsg(L"you cannot iterate through space table when the space is added without a wrapper"); // IMPROVE the message
return false; // return false;
find_helper.result->set(*space, false);
return true;
} }
else else
if( !IsTestingFunctionExistence() ) if( !IsTestingFunctionExistence() )
@ -1946,9 +1964,7 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::FindVaria
if( find_helper.found ) if( find_helper.found )
{ {
if( find_helper.result->type != Var<StreamType>::TYPE_MODEL && if( find_helper.result->type != Var<StreamType>::TYPE_MODEL ) // TYPE_SPACE here too?
find_helper.result->type != Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER &&
find_helper.result->type != Var<StreamType>::TYPE_SPACE_WRAPPER ) // TYPE_SPACE here too?
{ {
find_helper.input = find_helper.result; find_helper.input = find_helper.result;
} }
@ -1982,30 +1998,15 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::FindVaria
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream> template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateVariable(FindHelper & find_helper) void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateVariable(FindHelper & find_helper)
{ {
Var<StreamType> * result_child = nullptr; bool was_child_found = false;
find_helper.found = false; find_helper.found = false;
find_helper.current_var = nullptr; find_helper.current_var = nullptr;
const std::wstring & name = find_helper.current_name(); const std::wstring & name = find_helper.current_name();
if( find_helper.previous_var ) if( find_helper.previous_var )
{ {
if( find_helper.previous_var->type == Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER && name == L"val" && find_helper.field_index < find_helper.fields.size() ) find_helper.current_var = find_helper.previous_var->find_child(name);
{ find_helper.found = was_child_found = (find_helper.current_var != nullptr);
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 ) if( find_helper.current_var )
*find_helper.result = *find_helper.current_var; *find_helper.result = *find_helper.current_var;
@ -2014,11 +2015,14 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
if( !find_helper.found && find_helper.previous_name && find_helper.previous_result ) if( !find_helper.found && find_helper.previous_name && find_helper.previous_result )
{ {
if( find_helper.previous_result->type == Var<StreamType>::TYPE_MODEL || if( find_helper.previous_result->type == Var<StreamType>::TYPE_MODEL )
find_helper.previous_result->type == Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER )
{ {
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; return;
// what about if EvaluateModel returns another model or a space? we need a loop here?
} }
else else
if( find_helper.previous_result->type == Var<StreamType>::TYPE_SPACE ) if( find_helper.previous_result->type == Var<StreamType>::TYPE_SPACE )
@ -2029,7 +2033,7 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
} }
// find_helper.field_index could have been changed by EvaluateModelField or CallSpace // 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(); const std::wstring & name = find_helper.current_name();
@ -2065,7 +2069,7 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
find_helper.result->type = Var<StreamType>::Type::TYPE_STREAM; find_helper.result->type = Var<StreamType>::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? // may only model_container_wrapper and space_wrapper here?
//find_helper.result->type == Var<StreamType>::TYPE_MODEL || //find_helper.result->type == Var<StreamType>::TYPE_MODEL ||
@ -2074,34 +2078,22 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
find_helper.result->type == Var<StreamType>::TYPE_SPACE_WRAPPER || find_helper.result->type == Var<StreamType>::TYPE_SPACE_WRAPPER ||
find_helper.result->type == Var<StreamType>::TYPE_FUNCTION ) find_helper.result->type == Var<StreamType>::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<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER && find_helper.result->model_container_wrapper ) if( find_helper.result->type == Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER )
{ {
if( find_helper.is_last_field() && is_generating_for ) if( !EvaluateModelWrapper(find_helper) )
{ return;
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
}
} }
else
if( result_child ) if( find_helper.result->type == Var<StreamType>::TYPE_SPACE_WRAPPER )
{ {
if( result_child->type == Var<StreamType>::TYPE_SPACE_WRAPPER && result_child->space_wrapper ) if( !CallSpaceWrapper(*find_helper.result->space_wrapper, find_helper) )
{ return;
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_var = find_helper.current_var;
@ -2116,51 +2108,11 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
} }
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream> template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateModelField(FindHelper & find_helper) bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateModel(FindHelper & find_helper)
{ {
if( find_helper.previous_result->type == Var<StreamType>::TYPE_MODEL ) find_helper.found = CallModelField(*find_helper.previous_result->model, find_helper);
{
//find_helper.result->clear();
find_helper.found = CallModelField(*find_helper.previous_result->model, find_helper);
}
else
if( find_helper.previous_result->type == Var<StreamType>::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;
}
}
if( find_helper.found ) if( find_helper.found )
{ {
@ -2177,6 +2129,57 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateM
} }
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::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<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream> template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateFunction(typename Var<StreamType>::UserFunction user_function, FindHelper & find_helper) void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateFunction(typename Var<StreamType>::UserFunction user_function, FindHelper & find_helper)
@ -2733,7 +2736,23 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::MakeTextF
{ {
if( output_stream ) if( output_stream )
{ {
result.serialize_to(*output_stream); if( result.type == Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER )
{
// IMPROVEME add model_container serialized as a table
// add a method 'serialize_to' to ModelContainerWrapper
}
else
if( result.type == Var<StreamType>::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);
}
} }
} }

View File

@ -47,8 +47,6 @@
namespace morm namespace morm
{ {
class Model; class Model;
class ModelContainerWrapper;
class SpaceWrapper;
} }
@ -868,10 +866,6 @@ void Var<StreamType>::serialize_to(pt::WTextStream & str)
switch(type) switch(type)
{ {
case TYPE_SPACE_LOCAL: case TYPE_SPACE_LOCAL:
// case TYPE_BOOL:
// case TYPE_LONG:
// case TYPE_DOUBLE:
// case TYPE_STRING:
space_local.serialize_to_string(str); space_local.serialize_to_string(str);
break; break;
@ -885,8 +879,11 @@ void Var<StreamType>::serialize_to(pt::WTextStream & str)
case TYPE_VOID: case TYPE_VOID:
case TYPE_FUNCTION: case TYPE_FUNCTION:
break;
case TYPE_MODEL: case TYPE_MODEL:
case TYPE_MODEL_CONTAINER_WRAPPER: case TYPE_MODEL_CONTAINER_WRAPPER:
// 'model' is a forward declaration, we cannot call 'to_text' method
break; break;
case TYPE_SPACE_WRAPPER: case TYPE_SPACE_WRAPPER: