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:
parent
c4f5f79218
commit
fd2194623a
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
102
src/generator.h
102
src/generator.h
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue