WIP: add a for-in statement
This commit is contained in:
110
src/generator.h
110
src/generator.h
@@ -36,8 +36,8 @@
|
|||||||
#ifndef headerfile_ezc_generator
|
#ifndef headerfile_ezc_generator
|
||||||
#define headerfile_ezc_generator
|
#define headerfile_ezc_generator
|
||||||
|
|
||||||
#include <sstream>
|
//#include <sstream>
|
||||||
#include <fstream>
|
//#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "blocks.h"
|
#include "blocks.h"
|
||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
@@ -191,6 +191,15 @@ private:
|
|||||||
size_t block_stack_index;
|
size_t block_stack_index;
|
||||||
size_t block_stack_size;
|
size_t block_stack_size;
|
||||||
|
|
||||||
|
struct ForIn
|
||||||
|
{
|
||||||
|
// one Var for each for-in
|
||||||
|
std::vector<Var> args;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::wstring, ForIn> ForInMap;
|
||||||
|
std::map<std::wstring, ForIn> for_in_map;
|
||||||
|
|
||||||
// current output stream (can be null)
|
// current output stream (can be null)
|
||||||
// at the beginning it is pointing to the main stream (to the StreamType argument passsed to Generate method)
|
// at the beginning it is pointing to the main stream (to the StreamType argument passsed to Generate method)
|
||||||
StreamType * output_stream;
|
StreamType * output_stream;
|
||||||
@@ -298,12 +307,14 @@ private:
|
|||||||
|
|
||||||
bool IsTestingFunctionExistence();
|
bool IsTestingFunctionExistence();
|
||||||
|
|
||||||
|
bool FindInForIn(Item::Function & item_fun, FindHelper & find_helper);
|
||||||
|
|
||||||
bool CheckBlockArgument(int arg_index, FindHelper & find_helper);
|
bool CheckBlockArgument(int arg_index, FindHelper & find_helper);
|
||||||
|
|
||||||
bool FindInCache(Item::Function & item_fun, FindHelper & find_helper);
|
bool FindInCache(Item::Function & item_fun, FindHelper & find_helper);
|
||||||
|
|
||||||
#ifdef EZC_HAS_MORM_LIBRARY
|
#ifdef EZC_HAS_MORM_LIBRARY
|
||||||
bool FindInModels(FindHelper & find_helper);
|
bool FindInModels(const std::wstring & name, FindHelper & find_helper);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper);
|
bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper);
|
||||||
@@ -413,6 +424,7 @@ private:
|
|||||||
void MakeTextIfDef(Item & item);
|
void MakeTextIfDef(Item & item);
|
||||||
void MakeTextIfNotDef(Item & item);
|
void MakeTextIfNotDef(Item & item);
|
||||||
void MakeTextFor(Item & item);
|
void MakeTextFor(Item & item);
|
||||||
|
void MakeTextForIn(Item & item);
|
||||||
void MakeItemText(Item & item);
|
void MakeItemText(Item & item);
|
||||||
void MakeTextContainer(Item & item);
|
void MakeTextContainer(Item & item);
|
||||||
void MakeTextFunction(Item & item);
|
void MakeTextFunction(Item & item);
|
||||||
@@ -520,6 +532,7 @@ Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::operator=(cons
|
|||||||
|
|
||||||
// don't copy filter tab
|
// don't copy filter tab
|
||||||
// don't copy stack
|
// don't copy stack
|
||||||
|
// don't copy for_in_map
|
||||||
// don't copy ezc_frame_stack_tab
|
// don't copy ezc_frame_stack_tab
|
||||||
// don't copy output_stream and output_frames_streams
|
// don't copy output_stream and output_frames_streams
|
||||||
|
|
||||||
@@ -1010,6 +1023,45 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::IsTesting
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
|
||||||
|
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::FindInForIn(Item::Function & item_fun, FindHelper & find_helper)
|
||||||
|
{
|
||||||
|
#ifdef EZC_HAS_MORM_LIBRARY
|
||||||
|
|
||||||
|
if( item_fun.parameters.size() != 1 )
|
||||||
|
{
|
||||||
|
CreateMsg(L"incorrect parameter for for-in statement GIVE ME a better error description");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename ForInMap::iterator iterator = for_in_map.find(item_fun.name);
|
||||||
|
|
||||||
|
if( iterator != for_in_map.end() )
|
||||||
|
{
|
||||||
|
if( !iterator->second.args.empty() )
|
||||||
|
{
|
||||||
|
if( FindInModels(item_fun.parameters[0]->name, find_helper) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// if( !item_fun.fields.empty() && !IsTestingFunctionExistence() )
|
||||||
|
// {
|
||||||
|
// CreateMsg(L"unknown model", find_helper.fun_name->c_str());
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
CreateMsg(L"unknown model used in a for-in statement", find_helper.fun_name->c_str());
|
||||||
|
|
||||||
|
|
||||||
|
//find_helper.variable = &(iterator->second.args.back());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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>::CheckBlockArgument(int arg_index, FindHelper & find_helper)
|
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CheckBlockArgument(int arg_index, FindHelper & find_helper)
|
||||||
{
|
{
|
||||||
@@ -1066,11 +1118,11 @@ return false;
|
|||||||
#ifdef EZC_HAS_MORM_LIBRARY
|
#ifdef EZC_HAS_MORM_LIBRARY
|
||||||
|
|
||||||
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>::FindInModels(FindHelper & find_helper)
|
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::FindInModels(const std::wstring & name, FindHelper & find_helper)
|
||||||
{
|
{
|
||||||
if( pmodels )
|
if( pmodels )
|
||||||
{
|
{
|
||||||
morm::Wrapper * m = pmodels->Find(*find_helper.fun_name);
|
morm::Wrapper * m = pmodels->Find(name);
|
||||||
|
|
||||||
if( m )
|
if( m )
|
||||||
{
|
{
|
||||||
@@ -1151,11 +1203,14 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::FindInVar
|
|||||||
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>::Find(Item::Function & item_fun, FindHelper & find_helper)
|
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::Find(Item::Function & item_fun, FindHelper & find_helper)
|
||||||
{
|
{
|
||||||
|
if( FindInForIn(item_fun, find_helper) )
|
||||||
|
return true;
|
||||||
|
|
||||||
if( CheckBlockArgument(item_fun.arg, find_helper) )
|
if( CheckBlockArgument(item_fun.arg, find_helper) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#ifdef EZC_HAS_MORM_LIBRARY
|
#ifdef EZC_HAS_MORM_LIBRARY
|
||||||
if( FindInModels(find_helper) )
|
if( FindInModels(*find_helper.fun_name, find_helper) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( !item_fun.fields.empty() && !IsTestingFunctionExistence() )
|
if( !item_fun.fields.empty() && !IsTestingFunctionExistence() )
|
||||||
@@ -2615,6 +2670,48 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::MakeTextF
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
|
||||||
|
void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::MakeTextForIn(Item & item)
|
||||||
|
{
|
||||||
|
stack_tab[stack_index-1].is_for = true;
|
||||||
|
|
||||||
|
//for_in_map
|
||||||
|
|
||||||
|
for( ; !break_generating ; stack_tab[stack_index-1].iter += 1 )
|
||||||
|
{
|
||||||
|
if( stack_tab[stack_index-1].iter >= max_for_items )
|
||||||
|
{
|
||||||
|
CreateMsg(item.function.name.c_str(),
|
||||||
|
L"function exceeded a limit for a [for-in] statement");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMPLEMENT ME
|
||||||
|
|
||||||
|
|
||||||
|
// is_generating_for will be changed by next call to MakeText()
|
||||||
|
// so we should set it in each iterations
|
||||||
|
is_generating_for = true;
|
||||||
|
|
||||||
|
if( program_mode )
|
||||||
|
{
|
||||||
|
EvaluateProgramNode(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !Call(item.function, nullptr, stream_temp1, true, empty_stream) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !last_res )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( !item.item_tab.empty() )
|
||||||
|
MakeText( *item.item_tab[0] ); // should be only one item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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>::MakeTextDefine(Item & item, Var & var)
|
void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::MakeTextDefine(Item & item, Var & var)
|
||||||
{
|
{
|
||||||
@@ -3005,6 +3102,7 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::MakeText(
|
|||||||
else if( item.type == Item::item_let ) MakeTextLet(item);
|
else if( item.type == Item::item_let ) MakeTextLet(item);
|
||||||
else if( item.type == Item::item_let_if_not_set ) MakeTextLetIfNotSet(item);
|
else if( item.type == Item::item_let_if_not_set ) MakeTextLetIfNotSet(item);
|
||||||
else if( item.type == Item::item_for ) MakeTextFor(item);
|
else if( item.type == Item::item_for ) MakeTextFor(item);
|
||||||
|
else if( item.type == Item::item_for_in ) MakeTextForIn(item);
|
||||||
else if( item.type == Item::item_filter ) MakeTextFilter(item);
|
else if( item.type == Item::item_filter ) MakeTextFilter(item);
|
||||||
else if( item.type == Item::item_ezc ) MakeTextEzc(item);
|
else if( item.type == Item::item_ezc ) MakeTextEzc(item);
|
||||||
else if( item.type == Item::item_return ) MakeTextReturn(item);
|
else if( item.type == Item::item_return ) MakeTextReturn(item);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007-2021, Tomasz Sowa
|
* Copyright (c) 2007-2024, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -51,7 +51,7 @@ struct Item
|
|||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
item_none, item_container, item_text, item_function, item_if, item_if_def, item_if_not_def,
|
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_for_in, 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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007-2021, Tomasz Sowa
|
* Copyright (c) 2007-2024, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -34,7 +34,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "patternparser.h"
|
#include "patternparser.h"
|
||||||
#include "convert/convert.h"
|
#include "convert/text.h"
|
||||||
|
//#include "convert/convert.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -793,6 +794,17 @@ void PatternParser::ReadDirectiveFor(Item & item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PatternParser::ReadDirectiveForIn(Item & item)
|
||||||
|
{
|
||||||
|
item.type = Item::item_for_in;
|
||||||
|
|
||||||
|
if( ReadFunction(item) )
|
||||||
|
{
|
||||||
|
if( item.function.parameters.size() != 1 )
|
||||||
|
item.type = Item::item_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::ReadDirectiveComment(Item & item)
|
void PatternParser::ReadDirectiveComment(Item & item)
|
||||||
{
|
{
|
||||||
@@ -1022,6 +1034,7 @@ std::wstring name;
|
|||||||
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);
|
||||||
|
else if( name == L"for-in" ) ReadDirectiveForIn(item);
|
||||||
else if( name == L"include" ) ReadDirectiveInclude(item);
|
else if( name == L"include" ) ReadDirectiveInclude(item);
|
||||||
else if( name == L"def" ) ReadDirectiveDef(item);
|
else if( name == L"def" ) ReadDirectiveDef(item);
|
||||||
else if( name == L"def?" ) ReadDirectiveDefIfNotSet(item);
|
else if( name == L"def?" ) ReadDirectiveDefIfNotSet(item);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007-2021, Tomasz Sowa
|
* Copyright (c) 2007-2024, Tomasz Sowa
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -178,6 +178,7 @@ private:
|
|||||||
void ReadDirectiveEnd(Item & item);
|
void ReadDirectiveEnd(Item & item);
|
||||||
void ReadDirectiveElse(Item & item);
|
void ReadDirectiveElse(Item & item);
|
||||||
void ReadDirectiveFor(Item & item);
|
void ReadDirectiveFor(Item & item);
|
||||||
|
void ReadDirectiveForIn(Item & item);
|
||||||
void ReadDirectiveComment(Item & item);
|
void ReadDirectiveComment(Item & item);
|
||||||
void ReadDirectiveInclude(Item & item);
|
void ReadDirectiveInclude(Item & item);
|
||||||
void ReadDirectiveDef(Item & item);
|
void ReadDirectiveDef(Item & item);
|
||||||
|
|||||||
Reference in New Issue
Block a user