WIP: add a for-in statement

This commit is contained in:
2024-12-04 17:08:33 +01:00
parent d9ffe9b00a
commit 03b5c3d5a5
4 changed files with 126 additions and 14 deletions

View File

@@ -36,8 +36,8 @@
#ifndef headerfile_ezc_generator
#define headerfile_ezc_generator
#include <sstream>
#include <fstream>
//#include <sstream>
//#include <fstream>
#include <vector>
#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<Var> args;
};
typedef std::map<std::wstring, ForIn> ForInMap;
std::map<std::wstring, ForIn> 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<StreamType, is_pikotools_stream, is_autoescape_stream>::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<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>
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
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 )
{
morm::Wrapper * m = pmodels->Find(*find_helper.fun_name);
morm::Wrapper * m = pmodels->Find(name);
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>
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) )
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<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>
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_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);

View File

@@ -4,8 +4,8 @@
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* 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
};

View File

@@ -4,8 +4,8 @@
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* 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);

View File

@@ -4,8 +4,8 @@
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* 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);