[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.


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/