[opengtl-commits] [720] add a function to select which function is a best match for a given list of arguments |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/opengtl-commits Archives
]
Revision: 720
Author: cyrille
Date: 2009-04-11 14:42:30 +0200 (Sat, 11 Apr 2009)
Log Message:
-----------
add a function to select which function is a best match for a given list of arguments
Modified Paths:
--------------
trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp
trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.h
Modified: trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp
===================================================================
--- trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp 2009-04-11 11:57:40 UTC (rev 719)
+++ trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp 2009-04-11 12:42:30 UTC (rev 720)
@@ -44,6 +44,7 @@
#include "ConvertCenter_p.h"
#include "LexerBase_p.h"
#include "Debug.h"
+#include "Macros_p.h"
#include "Token_p.h"
#include "Function_p.h"
#include "Utils_p.h"
@@ -292,7 +293,16 @@
{
reportError("Unknown member: '" + name + "' for structure " + _expression->type()->structName(), d->currentToken );
} else {
- std::list<AST::Expression*> arguments = parseArguments( sfm->name(), sfm->parameters(), 1 );
+ std::list<Function*> functions;
+ std::list<AST::Expression*> arguments = parseArguments( sfm->name() );
+ functions.push_back(const_cast<Function*>( sfm->function() ) );
+ GTLCore::Function* function = 0;
+ arguments = selectFunction(arguments, functions, &function, 1);
+ if( not function )
+ {
+ return 0;
+ }
+ GTL_ASSERT(function == sfm->function());
return new AST::FunctionMemberAccessorExpression(_expression, sfm, arguments);
}
} else if( _expression->type()->dataType() == Type::STRUCTURE ) {
@@ -1352,15 +1362,20 @@
return 0;
}
GTL_ASSERT( not functionlist->empty() );
- Function* function = functionlist->front(); // TODO check for multiple arguments
getNextToken();
// Parse arguments
- std::list<AST::Expression*> arguments = parseArguments( function->name().toString(), function->parameters(), 0 );
+ std::list<AST::Expression*> arguments = parseArguments( fname.toString() );
+ GTLCore::Function* function = 0;
+ arguments = selectFunction(arguments, *functionlist, &function, 0);
+ if( not function )
+ {
+ return 0;
+ }
if( arguments.size() >= function->d->data->minimumParameters() and arguments.size() <= function->d->data->maximumParameters() )
{
return new AST::FunctionCallExpression( function, arguments ) ;
} else {
- reportError("Incorrect number of paramaters", d->currentToken);
+ reportError("Incorrect number of paramaters to function: " + function->name().toString(), d->currentToken);
return 0;
}
} else {
@@ -1388,7 +1403,7 @@
return 0;
}
-std::list<AST::Expression*> ParserBase::parseArguments( const String& _name, const std::vector< Parameter >& _parameters, int firstParameter )
+std::list<AST::Expression*> ParserBase::parseArguments( const String& _name )
{
std::list<AST::Expression*> arguments;
while(true)
@@ -1396,32 +1411,13 @@
if( d->currentToken.type == Token::ENDBRACKET )
{
break;
- } else if( arguments.size() + firstParameter == _parameters.size() ) {
- // Too much arguments
- reportError( "Too many arguments for function '" + _name + "'", d->currentToken);
- return arguments;
} else {
- int posArg = arguments.size();
AST::Expression* expression = parseExpression( false, 0 );
if(not expression)
{
return arguments;
}
- GTL_DEBUG( *_parameters[ posArg + firstParameter ].type() << " " << *expression->type() );
- expression = d->compiler->convertCenter()->createConvertExpression( expression, _parameters[ posArg + firstParameter ].type() );
- if( not expression )
- {
- reportError("Can't convert parameter " + String::number( posArg + 1 ), d->currentToken );
- return arguments;
- }
arguments.push_back( expression);
- if( _parameters[ posArg + firstParameter ].output() )
- {
- if( not dynamic_cast< AST::AccessorExpression* >( expression ) )
- {
- reportError( "Parameter of function '" + _name + "' is an output parameter and requires a variable as argument", d->currentToken );
- }
- }
if( d->currentToken.type == Token::COMA )
{
getNextToken();
@@ -1438,6 +1434,52 @@
return arguments;
}
+std::list<AST::Expression*> ParserBase::selectFunction( const std::list<AST::Expression*>& _expressions, const std::list<GTLCore::Function*>& _functions, GTLCore::Function** _selectedFunction, int firstParameter)
+{
+ GTL_ASSERT( _functions.size() > 0 );
+ GTL_ASSERT( *_selectedFunction == 0 );
+ if( _functions.size() == 1 )
+ {
+ GTLCore::Function* function = _functions.front();
+ std::size_t realNumber = firstParameter + _expressions.size();
+ GTL_DEBUG( function->name().toString() << " " << function->d->data->minimumParameters() << " " << realNumber << " " << function->d->data->maximumParameters() );
+ if( function->d->data->minimumParameters() > realNumber
+ or realNumber > function->d->data->maximumParameters() )
+ {
+ reportError("Invalid number of arguments for function: " + function->name().toString() + ".", currentToken());
+ return _expressions;
+ }
+ *_selectedFunction = function;
+ } else {
+ GTL_ABORT("Unimplemented");
+ }
+ // Attempt conversion
+ std::list<AST::Expression*> convertedExpressions;
+ GTLCore::Function* function = *_selectedFunction;
+ foreach( AST::Expression* expression, _expressions )
+ {
+ int posArg = convertedExpressions.size();
+ expression = d->compiler->convertCenter()->createConvertExpression( expression,
+ function->parameters()[ posArg + firstParameter ].type() );
+ if( not expression )
+ {
+ reportError("Can't convert parameter " + String::number( posArg + 1 ), d->currentToken );
+ return convertedExpressions;
+ }
+ convertedExpressions.push_back( expression);
+ if( function->parameters()[ posArg + firstParameter ].output() )
+ {
+ if( not dynamic_cast< AST::AccessorExpression* >( expression ) )
+ {
+ reportError( "Parameter of function '" + function->name().toString() + "' is an output parameter and requires a variable as argument", d->currentToken );
+ }
+ }
+
+ }
+ GTL_ASSERT( convertedExpressions.size() == _expressions.size() );
+ return convertedExpressions;
+}
+
void ParserBase::reachNextSemi()
{
while( d->currentToken.type != Token::SEMI and d->currentToken.type != Token::END_OF_FILE )
Modified: trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.h
===================================================================
--- trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.h 2009-04-11 11:57:40 UTC (rev 719)
+++ trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.h 2009-04-11 12:42:30 UTC (rev 720)
@@ -30,6 +30,7 @@
namespace GTLCore {
class ArraySize;
class VariableNG;
+ class Function;
class Type;
class ScopedName;
class CompilerBase;
@@ -112,7 +113,8 @@
/**
* Parse the arguments of a function.
*/
- std::list<AST::Expression*> parseArguments( const String& _name, const std::vector< Parameter >& _parameters, int firstParameter );
+ std::list<AST::Expression*> parseArguments( const String& _name );
+ std::list<AST::Expression*> selectFunction( const std::list<AST::Expression*>& _expressions, const std::list<GTLCore::Function*>& _functions, GTLCore::Function** _selectedFunction, int firstParameter);
/**
* Parse statement of the style "[ 10 ]" or "[ 2 + 3 ]", it's use for variables
* or constants definition.