changed: now [for] statements with the same function can be nested

sample:
[for my_function]
 [for my_function]
   foo
 [end]
[end]

changed: FunInfo::iter has a value from the last [for] statement now
sample:
[for my_function]
 [other_function]
[end]

void other_function(Info &i)
{
// here i.iter is the number of iteration
// previously was always zero
}

changed: small optimization in [for]
the proper function is being looking for only once at the beginning
previously it was searched in each iteration



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@331 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2011-01-14 23:59:30 +00:00
parent c4f5f79218
commit fd2194623a
4 changed files with 82 additions and 65 deletions

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2007-2010, Tomasz Sowa
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -64,8 +64,6 @@ public:
UserFunction user_function; // used when type is 'function'
std::wstring variable; // used when type is 'variable'
int iter;
bool is_for; // true if is used by a [for] statement
bool is_running; // true if this function is currently executed
Function();
@ -103,8 +101,6 @@ Functions<StreamType>::Function::Function()
{
type = Functions::variable;
user_function = 0;
iter = 0;
is_for = false;
is_running = false;
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2007-2010, Tomasz Sowa
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -55,16 +55,17 @@ struct FunInfo
StreamType & out;
// table of parameters
// the table can be empty
std::vector<std::wstring> & params;
// the first parameter
// you can always use it even if there is not any parameters
// you can always use it even if there is not any parameters (params is empty)
// in such a way the reference points to an empty string
const std::wstring & par;
// this is set by Generator
// normally is 0
// in a [for] statement it indicates the number of the current iteration (the first is 0)
// it indicates the number of a current iteration in the last [for] statement (the first is 0)
// if there was not any [for] before the value is zero
int iter;
// return value from a user function (default false if not set directly by the user function)

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2007-2010, Tomasz Sowa
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -109,10 +109,21 @@ private:
const std::wstring empty;
// a stack item for 'for' statements
// currently only one item (iteration)
struct StackItem
{
int iter;
};
// a stack for 'for' statements
std::vector<StackItem> stack_tab;
bool Find(const Item::Function & item_fun, typename Functions<StreamType>::Function ** function);
void Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
bool Call(Item::Function & function, bool * info_res = 0, typename Functions<StreamType>::Function ** pfun = 0);
void Call(typename Functions<StreamType>::Function * function, std::vector<std::wstring> & params, bool * info_res = 0);
void CallUserFunction(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
void CallVariable(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
@ -131,7 +142,7 @@ private:
void CreateUnknownMsg(const std::wstring & fun);
void MakeTextIf_go(Item & item, bool result);
bool MakeTextIfindexnumber(Item & item, typename Functions<StreamType>::Function * function, bool & result);
bool MakeTextIfindexnumber(Item & item, bool & result);
void MakeTextIf(Item & item);
void MakeTextIfno(Item & item);
void MakeTextIfany(Item & item);
@ -290,7 +301,11 @@ template<class StreamType>
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info)
{
info.Clear();
info.iter = function->iter;
if( stack_tab.empty() )
info.iter = 0;
else
info.iter = stack_tab.back().iter;
if( function->type == Functions<StreamType>::function )
CallUserFunction(function, info);
@ -344,6 +359,30 @@ return called;
// it calls the function pointed by pfun
template<class StreamType>
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function, std::vector<std::wstring> & params, bool * info_res)
{
if( params.empty() )
{
FunInfo<StreamType> info(*output_stream, params, empty);
Call(function, info);
if( info_res )
*info_res = info.res;
}
else
{
FunInfo<StreamType> info(*output_stream, params, params[0]);
Call(function, info);
if( info_res )
*info_res = info.res;
}
}
template<class StreamType>
wchar_t Generator<StreamType>::CreateSpecialChar(wchar_t c)
@ -746,12 +785,12 @@ bool info_res1, info_res2;
template<class StreamType>
bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, typename Functions<StreamType>::Function * function, bool & result)
bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, bool & result)
{
if( item.functions.size() != 2 )
if( item.functions.size() != 1 || stack_tab.empty() )
return false;
const wchar_t * number_text = item.functions[1].name.c_str();
const wchar_t * number_text = item.functions[0].name.c_str();
const wchar_t * last_char;
int number = StrToInt(number_text, &last_char);
@ -762,7 +801,7 @@ bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, typename Function
return false;
}
result = (function->iter == number);
result = (stack_tab.back().iter == number);
return true;
}
@ -772,39 +811,33 @@ return true;
template<class StreamType>
void Generator<StreamType>::MakeTextIfindex(Item & item)
{
if( item.functions.size() != 2 )
return;
// we actually don't call a function (or variable) here
// but only reading the iterator
typename Functions<StreamType>::Function * function;
if( !Find(item.functions[0], &function) )
if( item.functions.size() != 1 )
return;
bool result = false;
if( item.functions[1].name == L"odd" )
if( !stack_tab.empty() )
{
result = (function->iter & 1) == 1;
if( item.functions[0].name == L"odd" )
{
result = (stack_tab.back().iter & 1) == 1;
}
else
if( item.functions[1].name == L"even" )
if( item.functions[0].name == L"even" )
{
result = (function->iter & 1) == 0;
result = (stack_tab.back().iter & 1) == 0;
}
else
if( item.functions[1].name == L"first" )
if( item.functions[0].name == L"first" )
{
result = function->iter == 0;
result = stack_tab.back().iter == 0;
}
else
{
if( !MakeTextIfindexnumber(item, function, result) )
if( !MakeTextIfindexnumber(item, result) )
return;
}
}
MakeTextIf_go(item, result);
}
@ -816,16 +849,16 @@ void Generator<StreamType>::MakeTextForLoop(Item & item, typename Functions<Stre
{
bool info_res;
for( ; !break_generating ; function->iter += 1 )
for( ; !break_generating ; stack_tab.back().iter += 1 )
{
if( function->iter >= max_for_items )
if( stack_tab.back().iter >= max_for_items )
{
CreateMsg(item.functions[0].name.c_str(),
L"function exceeded a limit for a [for] statement");
break;
}
Call(item.functions[0], &info_res);
Call(function, item.functions[0].params, &info_res);
if( !info_res )
break;
@ -847,20 +880,13 @@ void Generator<StreamType>::MakeTextFor(Item & item)
if( !Find(item.functions[0], &function) )
return;
if( function->is_for )
{
CreateMsg(item.functions[0].name.c_str(),
L"this function is already used in a [for] statement");
return;
}
function->is_for = true;
function->iter = 0;
StackItem s;
s.iter = 0;
stack_tab.push_back(s);
MakeTextForLoop(item, function);
function->is_for = false;
function->iter = 0;
stack_tab.erase(--stack_tab.end());
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2007-2010, Tomasz Sowa
* Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -754,12 +754,6 @@ void Pattern::ReadDirectiveIfindex(Item & item)
item.functions.clear();
temp_function.params.clear();
// reading function name
if( !ReadName(temp_function.name) )
return;
item.functions.push_back(temp_function);
// reading: odd, even, first or a number (without quotes)
if( !ReadName(temp_function.name) )
return;