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;
}
// 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<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>
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)
{
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<StreamType, is_pikotools_stream, is_autoescape_stream>::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<StreamType, is_pikotools_stream, is_autoescape_stream>::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<StreamType, is_pikotools_stream, is_autoescape_stream>::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<StreamType, is_pikotools_stream, is_autoescape_stream>::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<StreamType, is_pikotools_stream, is_autoescape_stream>::FindVaria
if( find_helper.found )
{
if( find_helper.result->type != Var<StreamType>::TYPE_MODEL &&
find_helper.result->type != Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER &&
find_helper.result->type != Var<StreamType>::TYPE_SPACE_WRAPPER ) // TYPE_SPACE here too?
if( find_helper.result->type != Var<StreamType>::TYPE_MODEL ) // TYPE_SPACE here too?
{
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>
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.current_var = nullptr;
const std::wstring & name = find_helper.current_name();
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() )
{
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<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
if( !find_helper.found && find_helper.previous_name && find_helper.previous_result )
{
if( find_helper.previous_result->type == Var<StreamType>::TYPE_MODEL ||
find_helper.previous_result->type == Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER )
if( find_helper.previous_result->type == Var<StreamType>::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<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
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<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
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?
//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_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 )
{
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<StreamType>::TYPE_SPACE_WRAPPER )
{
if( result_child->type == Var<StreamType>::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<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
}
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.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;
}
}
find_helper.found = CallModelField(*find_helper.previous_result->model, find_helper);
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>
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 )
{
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
{
class Model;
class ModelContainerWrapper;
class SpaceWrapper;
}
@ -868,10 +866,6 @@ void Var<StreamType>::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<StreamType>::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: