[gtk+/wip/otte/shader: 30/55] gsksl: Add support for overloaded functions



commit 620c52987fb5ea283ae9d8bc8bf4fe9aefcdfbd3
Author: Benjamin Otte <otte redhat com>
Date:   Sat Sep 30 01:41:01 2017 +0200

    gsksl: Add support for overloaded functions
    
    This changes GskSlScope to allow multiple functions of the same name.
    
    It also introduces GskSlFunctionMatcher, which does overload matching in
    a way that can be used while parsing function calls.

 gsk/gskslcompiler.h          |    1 +
 gsk/gskslexpression.c        |  105 +++++++++++++++++------
 gsk/gskslexpressionprivate.h |    1 +
 gsk/gskslfunction.c          |  191 +++++++++++++++++++++++++++++++++++------
 gsk/gskslfunctionprivate.h   |   25 +++++-
 gsk/gskslnode.c              |   12 +++-
 gsk/gskslprogram.c           |    9 ++-
 gsk/gskslscope.c             |   38 ++++++---
 gsk/gskslscopeprivate.h      |    3 +-
 gsk/gsksltype.c              |   17 +++-
 gsk/gsksltypesprivate.h      |    1 +
 11 files changed, 326 insertions(+), 77 deletions(-)
---
diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h
index a042260..c5103f2 100644
--- a/gsk/gskslcompiler.h
+++ b/gsk/gskslcompiler.h
@@ -36,6 +36,7 @@ typedef enum {
   GSK_SL_COMPILER_ERROR_SYNTAX,
   GSK_SL_COMPILER_ERROR_TOKENIZER,
   GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
+  GSK_SL_COMPILER_ERROR_UNIQUENESS,
   GSK_SL_COMPILER_ERROR_UNSUPPORTED,
 } GskSlCompilerError;
 
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 9f5a3a3..5aaa29f 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -1280,16 +1280,14 @@ gsk_sl_constructor_get_args_by_type (const GskSlType *type)
 }
 
 GskSlExpression *
-gsk_sl_expression_parse_function_call (GskSlScope        *scope,
-                                       GskSlPreprocessor *stream,
-                                       GskSlFunction     *function)
+gsk_sl_expression_parse_function_call (GskSlScope           *scope,
+                                       GskSlPreprocessor    *stream,
+                                       GskSlFunctionMatcher *matcher,
+                                       GskSlFunction        *function)
 {
   GskSlExpressionFunctionCall *call;
   const GskSlToken *token;
-  GskSlType **types;
-  GError *error = NULL;
   gssize missing_args; /* only used for builtin constructors */
-  guint i;
 
   call = gsk_sl_expression_new (GskSlExpressionFunctionCall, &GSK_SL_EXPRESSION_FUNCTION_CALL);
 
@@ -1317,13 +1315,33 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
         {
           GskSlExpression *expression = gsk_sl_expression_parse_assignment (scope, stream);
 
-          g_ptr_array_add (arguments, expression);
-          
-          if (function == NULL)
+          if (function == NULL && matcher == NULL)
             {
               /* no checking necessary */
             }
-          if (missing_args == 0)
+          else if (matcher)
+            {
+              GskSlType *type = gsk_sl_expression_get_return_type (expression);
+
+              gsk_sl_function_matcher_match_argument (matcher, arguments->len, type);
+              if (!gsk_sl_function_matcher_has_matches (matcher))
+                {
+                  if (function)
+                    gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
+                                               "Cannot convert argument %u from %s to %s.",
+                                               arguments->len + 1,
+                                               gsk_sl_type_get_name (type),
+                                               gsk_sl_type_get_name (gsk_sl_function_get_argument_type 
(function, arguments->len)));
+                  else
+                    gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
+                                               "No overloaded function available that matches the first %u 
arguments",
+                                               arguments->len + 1);
+
+                  matcher = NULL;
+                  function = NULL;
+                }
+            }
+          else if (missing_args == 0)
             {
               gsk_sl_preprocessor_error (stream, ARGUMENT_COUNT,
                                          "Too many arguments given to builtin constructor, only the first %u 
are necessary.",
@@ -1348,6 +1366,8 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
                 }
             }
 
+          g_ptr_array_add (arguments, expression);
+          
           token = gsk_sl_preprocessor_get (stream);
           if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
             break;
@@ -1366,14 +1386,29 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
       call->arguments = (GskSlExpression **) g_ptr_array_free (arguments, FALSE);
     }
 
-  types = g_newa (GskSlType *, call->n_arguments);
-  for (i = 0; i < call->n_arguments; i++)
-    types[i] = gsk_sl_expression_get_return_type (call->arguments[i]);
-  if (function && missing_args < 0 && !gsk_sl_function_matches (function, types, call->n_arguments, &error))
+  if (matcher)
     {
-      gsk_sl_preprocessor_emit_error (stream, TRUE, gsk_sl_preprocessor_get_location (stream), error);
-      g_clear_error (&error);
-      function = NULL;
+      gsk_sl_function_matcher_match_n_arguments (matcher, call->n_arguments);
+      if (!gsk_sl_function_matcher_has_matches (matcher))
+        {
+          if (function)
+            gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
+                                       "Function %s needs %"G_GSIZE_FORMAT" arguments, but %u given.",
+                                       gsk_sl_function_get_name (function),
+                                       gsk_sl_function_get_n_arguments (function),
+                                       call->n_arguments);
+          else
+            gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
+                                       "No overloaded function available that matches this call");
+          function = NULL;
+        }
+      else
+        {
+          function = gsk_sl_function_matcher_get_match (matcher);
+          if (function == NULL)
+            gsk_sl_preprocessor_error (stream, UNIQUENESS,
+                                       "Cannot find unique match for overloaded function.");
+        }           
     }
 
   if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
@@ -1388,8 +1423,7 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
       gsk_sl_expression_unref ((GskSlExpression *) call);
       return gsk_sl_expression_error_new ();
     }
-  else
-
+  
   call->function = gsk_sl_function_ref (function);
   return (GskSlExpression *) call;
 }
@@ -1408,10 +1442,24 @@ gsk_sl_expression_parse_primary (GskSlScope        *scope,
       {
         GskSlExpression *expr;
         GskSlVariable *variable;
+        GskSlType *type;
         char *name;
         
-        if (gsk_sl_scope_lookup_type (scope, token->str))
-          goto its_a_type;
+        type = gsk_sl_scope_lookup_type (scope, token->str);
+        if (type)
+          {
+            GskSlFunctionMatcher matcher;
+            GskSlFunction *constructor;
+
+            constructor = gsk_sl_function_new_constructor (type);
+            gsk_sl_function_matcher_init (&matcher, g_list_prepend (NULL, constructor));
+            expr = gsk_sl_expression_parse_function_call (scope, stream, &matcher, constructor);
+            gsk_sl_function_matcher_finish (&matcher);
+            gsk_sl_function_unref (constructor);
+            gsk_sl_type_unref (type);
+
+            return expr;
+          }
 
         name = g_strdup (token->str);
         gsk_sl_preprocessor_consume (stream, NULL);
@@ -1419,12 +1467,18 @@ gsk_sl_expression_parse_primary (GskSlScope        *scope,
         token = gsk_sl_preprocessor_get (stream);
         if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
           {
-            GskSlFunction *function = gsk_sl_scope_lookup_function (scope, name);
+            GskSlFunctionMatcher matcher;
             
-            if (function == NULL)
+            gsk_sl_scope_match_function (scope, &matcher, name);
+            
+            if (!gsk_sl_function_matcher_has_matches (&matcher))
               gsk_sl_preprocessor_error (stream, DECLARATION, "No function named \"%s\".", name);
             
-            expr = gsk_sl_expression_parse_function_call (scope, stream, function);
+            expr = gsk_sl_expression_parse_function_call (scope, stream,
+                                                          &matcher,
+                                                          gsk_sl_function_matcher_get_match (&matcher));
+
+            gsk_sl_function_matcher_finish (&matcher);
           }
         else
           {
@@ -1550,10 +1604,9 @@ gsk_sl_expression_parse_primary (GskSlScope        *scope,
         GskSlExpression *expression;
         GskSlType *type;
 
-its_a_type:
         type = gsk_sl_type_new_parse (scope, stream);
         constructor = gsk_sl_function_new_constructor (type);
-        expression = gsk_sl_expression_parse_function_call (scope, stream, constructor);
+        expression = gsk_sl_expression_parse_function_call (scope, stream, NULL, constructor);
         gsk_sl_function_unref (constructor);
         gsk_sl_type_unref (type);
 
diff --git a/gsk/gskslexpressionprivate.h b/gsk/gskslexpressionprivate.h
index 3fb1811..02be57c 100644
--- a/gsk/gskslexpressionprivate.h
+++ b/gsk/gskslexpressionprivate.h
@@ -31,6 +31,7 @@ GskSlExpression *       gsk_sl_expression_parse_constant        (GskSlScope
                                                                  GskSlPreprocessor      *stream);
 GskSlExpression *       gsk_sl_expression_parse_function_call   (GskSlScope             *scope,
                                                                  GskSlPreprocessor      *stream,
+                                                                 GskSlFunctionMatcher   *matcher,
                                                                  GskSlFunction          *function);
 
 GskSlExpression *       gsk_sl_expression_ref                   (GskSlExpression        *expression);
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index 75d4f1b..779fe7f 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -568,46 +568,181 @@ gsk_sl_function_print (const GskSlFunction *function,
   function->class->print (function, string);
 }
 
+guint32
+gsk_sl_function_write_spv (const GskSlFunction *function,
+                           GskSpvWriter        *writer)
+{
+  return function->class->write_spv (function, writer);
+}
+
+void
+gsk_sl_function_matcher_init (GskSlFunctionMatcher *matcher,
+                              GList                *list)
+{
+  matcher->best_matches = list;
+  matcher->matches = NULL;
+}
+
+void
+gsk_sl_function_matcher_finish (GskSlFunctionMatcher *matcher)
+{
+  g_list_free (matcher->best_matches);
+  g_list_free (matcher->matches);
+}
+
 gboolean
-gsk_sl_function_matches (const GskSlFunction  *function,
-                         GskSlType           **arguments,
-                         gsize                 n_arguments,
-                         GError              **error)
+gsk_sl_function_matcher_has_matches (GskSlFunctionMatcher *matcher)
 {
-  guint i;
+  return matcher->best_matches || matcher->matches;
+}
+
+GskSlFunction *
+gsk_sl_function_matcher_get_match (GskSlFunctionMatcher *matcher)
+{
+  if (matcher->best_matches == NULL)
+    return NULL;
+
+  if (matcher->best_matches->next != NULL)
+    return NULL;
+
+  return matcher->best_matches->data;
+}
+
+void
+gsk_sl_function_matcher_match_n_arguments (GskSlFunctionMatcher *matcher,
+                                           gsize                 n_arguments)
+{
+  GList *l;
+
+  for (l = matcher->best_matches; l; l = l->next)
+    {
+      if (gsk_sl_function_get_n_arguments (l->data) != n_arguments)
+        matcher->best_matches = g_list_delete_link (matcher->best_matches, l);
+    }
+  for (l = matcher->matches; l; l = l->next)
+    {
+      if (gsk_sl_function_get_n_arguments (l->data) != n_arguments)
+        matcher->matches = g_list_delete_link (matcher->matches, l);
+    }
+}
+
+typedef enum {
+  MATCH_NONE,
+  MATCH_CONVERT_TO_DOUBLE,
+  MATCH_CONVERT,
+  MATCH_EXACT
+} GskSlFunctionMatch;
 
-  if (n_arguments != gsk_sl_function_get_n_arguments (function))
+static GskSlFunctionMatch
+gsk_sl_function_matcher_match_types (const GskSlType *function_type,
+                                     const GskSlType *argument_type)
+{
+  if (!gsk_sl_type_can_convert (function_type, argument_type))
+    return MATCH_NONE;
+
+  if (gsk_sl_type_equal (function_type, argument_type))
+    return MATCH_EXACT;
+
+  if (gsk_sl_type_get_scalar_type (function_type))
+    return MATCH_CONVERT_TO_DOUBLE;
+  
+  return MATCH_CONVERT;
+}
+
+void
+gsk_sl_function_matcher_match_argument (GskSlFunctionMatcher *matcher,
+                                        gsize                 n,
+                                        const GskSlType      *argument_type)
+{
+  GList *best_matches = NULL, *matches = NULL, *l;
+  GskSlFunctionMatch best = MATCH_NONE, function_match;
+
+  for (l = matcher->best_matches; l; l = l->next)
     {
-      g_set_error (error,
-                   GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
-                   "Function %s needs %"G_GSIZE_FORMAT" arguments, but %"G_GSIZE_FORMAT" given.",
-                   gsk_sl_function_get_name (function),
-                   gsk_sl_function_get_n_arguments (function),
-                   n_arguments);
-      return FALSE;
+      GskSlType *function_type;
+      GskSlFunctionMatch function_match;
+      
+      if (gsk_sl_function_get_n_arguments (l->data) <= n)
+        continue;
+
+      function_type = gsk_sl_function_get_argument_type (l->data, n);
+      function_match = gsk_sl_function_matcher_match_types (function_type, argument_type);
+      if (function_match == MATCH_NONE)
+        continue;
+
+      if (function_match == best)
+        {
+          best_matches = g_list_prepend (best_matches, l->data);
+          best = function_match;
+        }
+      else if (function_match > best)
+        {
+          matches = g_list_concat (matches, best_matches);
+          best_matches = g_list_prepend (NULL, l->data);
+          best = function_match;
+        }
+      else 
+        {
+          matches = g_list_prepend (matches, l->data);
+        }
     }
 
-  for (i = 0; i < n_arguments; i++)
+  for (l = matcher->matches; l; l = l->next)
     {
-      if (!gsk_sl_type_can_convert (gsk_sl_function_get_argument_type (function, i), arguments[i]))
+      GskSlType *function_type;
+      
+      if (gsk_sl_function_get_n_arguments (l->data) <= n)
+        continue;
+
+      function_type = gsk_sl_function_get_argument_type (l->data, n);
+      function_match = gsk_sl_function_matcher_match_types (function_type, argument_type);
+      if (function_match == MATCH_NONE)
+        continue;
+
+      if (function_match > best)
         {
-          g_set_error (error,
-                       GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
-                       "Cannot convert argument %u from %s to %s.",
-                       i + 1,
-                       gsk_sl_type_get_name (arguments[i]),
-                       gsk_sl_type_get_name (gsk_sl_function_get_argument_type (function, i)));
-          return FALSE;
+          matches = g_list_concat (matches, best_matches);
+          best_matches = NULL;
+          best = function_match;
         }
+      matches = g_list_prepend (matches, l->data);
     }
 
-  return TRUE;
+  g_list_free (matcher->best_matches);
+  g_list_free (matcher->matches);
+  matcher->best_matches = best_matches;
+  matcher->matches = matches;
 }
 
-guint32
-gsk_sl_function_write_spv (const GskSlFunction *function,
-                           GskSpvWriter        *writer)
+void
+gsk_sl_function_matcher_match_function (GskSlFunctionMatcher *matcher,
+                                        const GskSlFunction  *function)
 {
-  return function->class->write_spv (function, writer);
-}
+  GList *l;
+  gsize i, n;
+
+  n = gsk_sl_function_get_n_arguments (function);
+
+  for (l = matcher->best_matches; l; l = l->next)
+    {
+      GskSlFunction *f = l->data;
 
+      if (gsk_sl_function_get_n_arguments (f) != n)
+        continue;
+
+      for (i = 0; i < n; i++)
+        {
+          if (!gsk_sl_type_equal (gsk_sl_function_get_argument_type (f, i),
+                                  gsk_sl_function_get_argument_type (function, i)))
+            break;
+        }
+      if (i == n)
+        {
+          g_list_free (matcher->best_matches);
+          g_list_free (matcher->matches);
+          matcher->best_matches = g_list_prepend (NULL, f);
+          matcher->matches = NULL;
+          return;
+        }
+    }
+}
diff --git a/gsk/gskslfunctionprivate.h b/gsk/gskslfunctionprivate.h
index ce38b8e..92d11f7 100644
--- a/gsk/gskslfunctionprivate.h
+++ b/gsk/gskslfunctionprivate.h
@@ -67,13 +67,30 @@ GskSlType *             gsk_sl_function_get_return_type         (const GskSlFunc
 gsize                   gsk_sl_function_get_n_arguments         (const GskSlFunction    *function);
 GskSlType *             gsk_sl_function_get_argument_type       (const GskSlFunction    *function,
                                                                  gsize                   i);
-gboolean                gsk_sl_function_matches                 (const GskSlFunction    *function,
-                                                                 GskSlType             **arguments,
-                                                                 gsize                   n_arguments,
-                                                                 GError                **error);
 guint32                 gsk_sl_function_write_spv               (const GskSlFunction    *function,
                                                                  GskSpvWriter           *writer);
 
+struct _GskSlFunctionMatcher
+{
+  GList *best_matches;
+  GList *matches;
+};
+
+void                    gsk_sl_function_matcher_init            (GskSlFunctionMatcher   *matcher,
+                                                                 GList                  *list);
+void                    gsk_sl_function_matcher_finish          (GskSlFunctionMatcher   *matcher);
+
+gboolean                gsk_sl_function_matcher_has_matches     (GskSlFunctionMatcher   *matcher);
+GskSlFunction *         gsk_sl_function_matcher_get_match       (GskSlFunctionMatcher   *matcher);
+
+void                    gsk_sl_function_matcher_match_n_arguments (GskSlFunctionMatcher *matcher,
+                                                                 gsize                   n_arguments);
+void                    gsk_sl_function_matcher_match_argument  (GskSlFunctionMatcher   *matcher,
+                                                                 gsize                   n,
+                                                                 const GskSlType        *argument_type);
+void                    gsk_sl_function_matcher_match_function  (GskSlFunctionMatcher   *matcher,
+                                                                 const GskSlFunction    *function);
+
 G_END_DECLS
 
 #endif /* __GSK_SL_FUNCTION_PRIVATE_H__ */
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index 0e48d2e..b1fa4c4 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -402,7 +402,17 @@ its_a_type:
                 
             constructor = gsk_sl_function_new_constructor (type);
             node_expression = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
-            node_expression->expression = gsk_sl_expression_parse_function_call (scope, preproc, 
constructor);
+            if (gsk_sl_function_is_builtin_constructor (constructor))
+              {
+                node_expression->expression = gsk_sl_expression_parse_function_call (scope, preproc, NULL, 
constructor);
+              }
+            else
+              {
+                GskSlFunctionMatcher matcher;
+                gsk_sl_function_matcher_init (&matcher, g_list_prepend (NULL, constructor));
+                node_expression->expression = gsk_sl_expression_parse_function_call (scope, preproc, 
&matcher, constructor);
+                gsk_sl_function_matcher_finish (&matcher);
+              }
             node = (GskSlNode *) node_expression;
             gsk_sl_function_unref (constructor);
           }
diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c
index 3d47dd6..d9a78c9 100644
--- a/gsk/gskslprogram.c
+++ b/gsk/gskslprogram.c
@@ -175,13 +175,20 @@ gsk_sl_program_parse_declaration (GskSlProgram      *program,
 
   if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
     {
+      GskSlFunctionMatcher matcher;
       GskSlFunction *function;
 
       function = gsk_sl_function_new_parse (scope,
                                             preproc,
                                             type,
                                             name);
-      gsk_sl_scope_add_function (scope, function);
+      gsk_sl_scope_match_function (scope, &matcher, gsk_sl_function_get_name (function));
+      gsk_sl_function_matcher_match_function (&matcher, function);
+      if (gsk_sl_function_matcher_has_matches (&matcher))
+        gsk_sl_preprocessor_error (preproc, DECLARATION, "A function with the same prototype has already 
been defined.");
+      else
+        gsk_sl_scope_add_function (scope, function);
+      gsk_sl_function_matcher_finish (&matcher);
       program->functions = g_slist_append (program->functions, function);
     }
   else
diff --git a/gsk/gskslscope.c b/gsk/gskslscope.c
index 1a70c33..df1b630 100644
--- a/gsk/gskslscope.c
+++ b/gsk/gskslscope.c
@@ -20,8 +20,8 @@
 
 #include "gskslscopeprivate.h"
 
-#include "gsksltypeprivate.h"
 #include "gskslfunctionprivate.h"
+#include "gsksltypeprivate.h"
 #include "gskslvariableprivate.h"
 
 #include <string.h>
@@ -38,6 +38,12 @@ struct _GskSlScope
   GHashTable *types;
 };
 
+static void
+free_function_list (gpointer data)
+{
+  g_list_free_full (data, (GDestroyNotify) gsk_sl_function_unref);
+}
+
 GskSlScope *
 gsk_sl_scope_new (GskSlScope *parent,
                   GskSlType  *return_type)
@@ -52,7 +58,7 @@ gsk_sl_scope_new (GskSlScope *parent,
   if (return_type)
     scope->return_type = gsk_sl_type_ref (return_type);
   scope->variables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) 
gsk_sl_variable_unref);
-  scope->functions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) 
gsk_sl_function_unref);
+  scope->functions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) 
free_function_list);
   scope->types = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsk_sl_type_unref);
 
   return scope;
@@ -131,25 +137,35 @@ void
 gsk_sl_scope_add_function (GskSlScope    *scope,
                            GskSlFunction *function)
 {
-  g_hash_table_replace (scope->functions, gsk_sl_function_get_name (function), gsk_sl_function_ref 
(function));
+  GList *functions;
+  const char *name;
+
+  name = gsk_sl_function_get_name (function);
+
+  functions = g_hash_table_lookup (scope->functions, name);
+  gsk_sl_function_ref (function);
+  if (functions)
+    functions = g_list_append (functions, function);
+  else
+    g_hash_table_insert (scope->functions, name, g_list_prepend (NULL, function));
 }
 
-GskSlFunction *
-gsk_sl_scope_lookup_function (GskSlScope *scope,
-                              const char *name)
+void
+gsk_sl_scope_match_function (GskSlScope           *scope,
+                             GskSlFunctionMatcher *matcher,
+                             const char           *name)
 {
-  GskSlFunction *result;
+  GList *result = NULL, *lookup;
 
   for (;
        scope != NULL;
        scope = scope->parent)
     {
-      result = g_hash_table_lookup (scope->functions, name);
-      if (result)
-        return result;
+      lookup = g_hash_table_lookup (scope->functions, name);
+      result = g_list_concat (result, g_list_copy (lookup));
     }
 
-  return NULL;
+  gsk_sl_function_matcher_init (matcher, result);
 }
 
 void
diff --git a/gsk/gskslscopeprivate.h b/gsk/gskslscopeprivate.h
index 50e6120..6c6e865 100644
--- a/gsk/gskslscopeprivate.h
+++ b/gsk/gskslscopeprivate.h
@@ -40,7 +40,8 @@ GskSlVariable *         gsk_sl_scope_lookup_variable            (GskSlScope
                                                                  const char           *name);
 void                    gsk_sl_scope_add_function               (GskSlScope           *scope,
                                                                  GskSlFunction        *function);
-GskSlFunction *         gsk_sl_scope_lookup_function            (GskSlScope           *scope,
+void                    gsk_sl_scope_match_function             (GskSlScope           *scope,
+                                                                 GskSlFunctionMatcher *matcher,
                                                                  const char           *name);
 void                    gsk_sl_scope_add_type                   (GskSlScope           *scope,
                                                                  GskSlType            *type);
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index 22e60ed..a21d1c0 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -20,10 +20,10 @@
 
 #include "gsksltypeprivate.h"
 
-#include "gsksltokenizerprivate.h"
-#include "gskslpreprocessorprivate.h"
+#include "gskslfunctionprivate.h"
 #include "gskslpreprocessorprivate.h"
 #include "gskslscopeprivate.h"
+#include "gsksltokenizerprivate.h"
 #include "gskslvalueprivate.h"
 #include "gskspvwriterprivate.h"
 
@@ -1184,10 +1184,17 @@ out:
     {
       if (gsk_sl_scope_lookup_type (scope, gsk_sl_type_get_name (type)))
         gsk_sl_preprocessor_error (preproc, DECLARATION, "Redefinition of struct \"%s\".", 
gsk_sl_type_get_name (type));
-      else if (gsk_sl_scope_lookup_function (scope, gsk_sl_type_get_name (type)))
-        gsk_sl_preprocessor_error (preproc, DECLARATION, "Constructor name \"%s\" would override function of 
same name.", gsk_sl_type_get_name (type));
       else
-        gsk_sl_scope_add_type (scope, type);
+        {
+          GskSlFunctionMatcher matcher;
+          
+          gsk_sl_scope_match_function (scope, &matcher, gsk_sl_type_get_name (type));
+          if (gsk_sl_function_matcher_has_matches (&matcher))
+            gsk_sl_preprocessor_error (preproc, DECLARATION, "Constructor name \"%s\" would override 
function of same name.", gsk_sl_type_get_name (type));
+          else
+            gsk_sl_scope_add_type (scope, type);
+          gsk_sl_function_matcher_finish (&matcher);
+        }
     }
   return type;
 }
diff --git a/gsk/gsksltypesprivate.h b/gsk/gsksltypesprivate.h
index cd15ae1..3a7125f 100644
--- a/gsk/gsksltypesprivate.h
+++ b/gsk/gsksltypesprivate.h
@@ -23,6 +23,7 @@
 
 typedef struct _GskSlExpression         GskSlExpression;
 typedef struct _GskSlFunction           GskSlFunction;
+typedef struct _GskSlFunctionMatcher    GskSlFunctionMatcher;
 typedef struct _GskSlNode               GskSlNode;
 typedef struct _GskSlPreprocessor       GskSlPreprocessor;
 typedef struct _GskSlPointerType        GskSlPointerType;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]