[opengtl-commits] [722] implement selection of the best overloaded function

[ Thread Index | Date Index | More lists.tuxfamily.org/opengtl-commits Archives ]


Revision: 722
Author:   cyrille
Date:     2009-04-11 15:53:23 +0200 (Sat, 11 Apr 2009)

Log Message:
-----------
implement selection of the best overloaded function

Modified Paths:
--------------
    trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp


Modified: trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp
===================================================================
--- trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp	2009-04-11 13:52:08 UTC (rev 721)
+++ trunk/OpenGTL/OpenGTL/GTLCore/ParserBase_p.cpp	2009-04-11 13:53:23 UTC (rev 722)
@@ -1438,13 +1438,13 @@
 {
   GTL_ASSERT( _functions.size() > 0 );
   GTL_ASSERT( *_selectedFunction == 0 );
+  std::size_t realParameterCount = firstParameter + _expressions.size();
   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() )
+    GTL_DEBUG( function->name().toString()  << " " << function->d->data->minimumParameters()  << " " << realParameterCount << " " << function->d->data->maximumParameters() );
+    if( function->d->data->minimumParameters() > realParameterCount
+        or realParameterCount > function->d->data->maximumParameters() )
     {
       reportError("Invalid number of arguments for function: " + function->name().toString() + ".", currentToken());
       return _expressions;
@@ -1452,10 +1452,82 @@
     *_selectedFunction = function;
   } else {
     GTL_ABORT("Unimplemented");
+    GTLCore::Function* bestFunction = 0;
+    int bestLosslessConversionCount = _expressions.size() + 1;
+    int bestLossConversionCount = _expressions.size() + 1;
+    foreach( GTLCore::Function* function, _functions)
+    {
+      GTL_DEBUG("Test for " << *function);
+      if( function->d->data->minimumParameters() <= realParameterCount
+          and realParameterCount <= function->d->data->maximumParameters() )
+      {
+        GTL_DEBUG("Good range of arguments");
+        int posArg = 0;
+        int currentLossLessConversionCount = 0;
+        int currentLossConversionCount = 0;
+        bool canUse = true;
+        foreach( AST::Expression* expression, _expressions)
+        {
+          if( function->parameters()[ posArg + firstParameter ].output() )
+          {
+            if( not dynamic_cast< AST::AccessorExpression* >( expression ) )
+            {
+              // Not an accessor, meaning we can't use that function since the parameter is an output
+              canUse = false;
+              break;
+            }
+          }
+          ConvertCenter::ConversionQuality cq = d->compiler->convertCenter()->conversionQuality( expression->type(), function->parameters()[ posArg + firstParameter ].type());
+          GTL_DEBUG("Quality for " << posArg << " " << cq);
+          if( cq == ConvertCenter::NOT_CONVERTIBLE )
+          {
+            canUse = false;
+            break;
+          } else {
+            switch(cq)
+            {
+              case ConvertCenter::NOT_CONVERTIBLE:
+                GTL_ABORT("Shouldn't be possible");
+              case ConvertCenter::NONEEDED_CONVERSION:
+                break;
+              case ConvertCenter::LOSS_CONVERSION:
+                ++currentLossConversionCount;
+                break;
+              case ConvertCenter::LOSSLESS_CONVERSION:
+                ++currentLossLessConversionCount;
+                break;
+            }
+          }
+          ++posArg;
+        }
+        if(canUse )
+        {
+          if( currentLossLessConversionCount == bestLosslessConversionCount and currentLossConversionCount == bestLossConversionCount )
+          {
+            // Can't know which function to use
+            bestFunction = 0;
+          } else if( currentLossConversionCount < bestLossConversionCount or (currentLossLessConversionCount < bestLosslessConversionCount and currentLossConversionCount <= bestLossConversionCount ) ) {
+            bestFunction = function;
+            bestLosslessConversionCount = currentLossLessConversionCount;
+            bestLossConversionCount = currentLossConversionCount;
+          }
+        }
+      }
+    }
+    if( bestFunction )
+    {
+      GTL_DEBUG("Best function " << *bestFunction);
+      *_selectedFunction = bestFunction;
+    } else {
+      *_selectedFunction = 0;
+      reportError("Can't find which overloaded functions of '" + _functions.front()->name().toString() + "' to use.", currentToken() );
+      return _expressions;
+    }
   }
   // Attempt conversion
   std::list<AST::Expression*> convertedExpressions;
   GTLCore::Function* function = *_selectedFunction;
+  GTL_ASSERT(function);
   foreach( AST::Expression* expression, _expressions )
   {
     int posArg = convertedExpressions.size();
@@ -1463,6 +1535,7 @@
                                   function->parameters()[ posArg  + firstParameter ].type() );
     if( not expression )
     {
+      *_selectedFunction = 0;
       reportError("Can't convert parameter " + String::number( posArg + 1 ), d->currentToken  );
       return convertedExpressions;
     }
@@ -1471,6 +1544,7 @@
     {
       if( not dynamic_cast< AST::AccessorExpression* >( expression ) )
       {
+        *_selectedFunction = 0;
         reportError( "Parameter of function '" + function->name().toString() + "' is an output parameter and requires a variable as argument", d->currentToken );
       }
     }


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