diff --git a/src/generator.h b/src/generator.h index 4d9de98..f9c9a41 100644 --- a/src/generator.h +++ b/src/generator.h @@ -36,8 +36,8 @@ #ifndef headerfile_ezc_generator #define headerfile_ezc_generator -#include -#include +//#include +//#include #include #include "blocks.h" #include "pattern.h" @@ -191,6 +191,15 @@ private: size_t block_stack_index; size_t block_stack_size; + struct ForIn + { + // one Var for each for-in + std::vector args; + }; + + typedef std::map ForInMap; + std::map for_in_map; + // current output stream (can be null) // at the beginning it is pointing to the main stream (to the StreamType argument passsed to Generate method) StreamType * output_stream; @@ -298,12 +307,14 @@ private: bool IsTestingFunctionExistence(); + bool FindInForIn(Item::Function & item_fun, FindHelper & find_helper); + bool CheckBlockArgument(int arg_index, FindHelper & find_helper); bool FindInCache(Item::Function & item_fun, FindHelper & find_helper); #ifdef EZC_HAS_MORM_LIBRARY - bool FindInModels(FindHelper & find_helper); + bool FindInModels(const std::wstring & name, FindHelper & find_helper); #endif bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper); @@ -413,6 +424,7 @@ private: void MakeTextIfDef(Item & item); void MakeTextIfNotDef(Item & item); void MakeTextFor(Item & item); + void MakeTextForIn(Item & item); void MakeItemText(Item & item); void MakeTextContainer(Item & item); void MakeTextFunction(Item & item); @@ -520,6 +532,7 @@ Generator::operator=(cons // don't copy filter tab // don't copy stack + // don't copy for_in_map // don't copy ezc_frame_stack_tab // don't copy output_stream and output_frames_streams @@ -1010,6 +1023,45 @@ bool Generator::IsTesting } +template +bool Generator::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 bool Generator::CheckBlockArgument(int arg_index, FindHelper & find_helper) { @@ -1066,11 +1118,11 @@ return false; #ifdef EZC_HAS_MORM_LIBRARY template -bool Generator::FindInModels(FindHelper & find_helper) +bool Generator::FindInModels(const std::wstring & name, FindHelper & find_helper) { if( pmodels ) { - morm::Wrapper * m = pmodels->Find(*find_helper.fun_name); + morm::Wrapper * m = pmodels->Find(name); if( m ) { @@ -1151,11 +1203,14 @@ bool Generator::FindInVar template bool Generator::Find(Item::Function & item_fun, FindHelper & find_helper) { + if( FindInForIn(item_fun, find_helper) ) + return true; + if( CheckBlockArgument(item_fun.arg, find_helper) ) return true; #ifdef EZC_HAS_MORM_LIBRARY - if( FindInModels(find_helper) ) + if( FindInModels(*find_helper.fun_name, find_helper) ) return true; if( !item_fun.fields.empty() && !IsTestingFunctionExistence() ) @@ -2615,6 +2670,48 @@ void Generator::MakeTextF } +template +void Generator::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 void Generator::MakeTextDefine(Item & item, Var & var) { @@ -3005,6 +3102,7 @@ void Generator::MakeText( 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_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_ezc ) MakeTextEzc(item); else if( item.type == Item::item_return ) MakeTextReturn(item); diff --git a/src/item.h b/src/item.h index ce812f8..e90a64b 100644 --- a/src/item.h +++ b/src/item.h @@ -4,8 +4,8 @@ * Author: Tomasz Sowa */ -/* - * Copyright (c) 2007-2021, Tomasz Sowa +/* + * Copyright (c) 2007-2024, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ struct Item enum Type { 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_filter, item_ezc, item_block, item_return }; diff --git a/src/patternparser.cpp b/src/patternparser.cpp index 0c7d456..af30c09 100644 --- a/src/patternparser.cpp +++ b/src/patternparser.cpp @@ -4,8 +4,8 @@ * Author: Tomasz Sowa */ -/* - * Copyright (c) 2007-2021, Tomasz Sowa +/* + * Copyright (c) 2007-2024, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,8 @@ #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) { @@ -1022,6 +1034,7 @@ std::wstring name; else if( name == L"end" ) ReadDirectiveEnd(item); else if( name == L"else" ) ReadDirectiveElse(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"def" ) ReadDirectiveDef(item); else if( name == L"def?" ) ReadDirectiveDefIfNotSet(item); diff --git a/src/patternparser.h b/src/patternparser.h index 9f981b4..350dbde 100644 --- a/src/patternparser.h +++ b/src/patternparser.h @@ -4,8 +4,8 @@ * Author: Tomasz Sowa */ -/* - * Copyright (c) 2007-2021, Tomasz Sowa +/* + * Copyright (c) 2007-2024, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -178,6 +178,7 @@ private: void ReadDirectiveEnd(Item & item); void ReadDirectiveElse(Item & item); void ReadDirectiveFor(Item & item); + void ReadDirectiveForIn(Item & item); void ReadDirectiveComment(Item & item); void ReadDirectiveInclude(Item & item); void ReadDirectiveDef(Item & item);