[gtk+/wip/otte/shader: 18/19] gskslfunction: Reorganize gsk_sl_function_matches()



commit 1a348fd3360b0c8c758b669dfc08377afb643400
Author: Benjamin Otte <otte redhat com>
Date:   Fri Sep 29 22:17:16 2017 +0200

    gskslfunction: Reorganize gsk_sl_function_matches()
    
    This is the first step towards implementing function overloading.
    
    Instead of having the matches() vfunc the code now can query argument
    type and count and uses this to implement a generic matches().
    
    Constructors are checked seperately and manually. They also report 0
    arguments.

 gsk/gskslcompiler.h        |    1 +
 gsk/gskslexpression.c      |   58 ++++++++++++-
 gsk/gskslfunction.c        |  219 +++++++++++++++++++-------------------------
 gsk/gskslfunctionprivate.h |   12 ++-
 4 files changed, 159 insertions(+), 131 deletions(-)
---
diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h
index 4a23007..a042260 100644
--- a/gsk/gskslcompiler.h
+++ b/gsk/gskslcompiler.h
@@ -28,6 +28,7 @@
 G_BEGIN_DECLS
 
 typedef enum {
+  GSK_SL_COMPILER_ERROR_ARGUMENT_COUNT,
   GSK_SL_COMPILER_ERROR_CONSTANT,
   GSK_SL_COMPILER_ERROR_DECLARATION,
   GSK_SL_COMPILER_ERROR_PREPROCESSOR,
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 8b81db8..9f5a3a3 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -1266,6 +1266,19 @@ gsk_sl_expression_error_new (void)
   return (GskSlExpression *) constant;
 }
 
+static gsize
+gsk_sl_constructor_get_args_by_type (const GskSlType *type)
+{
+  if (gsk_sl_type_is_scalar (type))
+    return 1;
+  else if (gsk_sl_type_is_vector (type))
+    return gsk_sl_type_get_length (type);
+  else if (gsk_sl_type_is_matrix (type))
+    return gsk_sl_type_get_length (type) * gsk_sl_constructor_get_args_by_type (gsk_sl_type_get_index_type 
(type));
+  else
+    return 0;
+}
+
 GskSlExpression *
 gsk_sl_expression_parse_function_call (GskSlScope        *scope,
                                        GskSlPreprocessor *stream,
@@ -1275,6 +1288,7 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
   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);
@@ -1288,6 +1302,11 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
     }
   gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
 
+  if (function && gsk_sl_function_is_builtin_constructor (function))
+    missing_args = gsk_sl_constructor_get_args_by_type (gsk_sl_function_get_return_type (function));
+  else
+    missing_args = -1;
+
   token = gsk_sl_preprocessor_get (stream);
   if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
     {
@@ -1300,12 +1319,49 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
 
           g_ptr_array_add (arguments, expression);
           
+          if (function == NULL)
+            {
+              /* no checking necessary */
+            }
+          if (missing_args == 0)
+            {
+              gsk_sl_preprocessor_error (stream, ARGUMENT_COUNT,
+                                         "Too many arguments given to builtin constructor, only the first %u 
are necessary.",
+                                         arguments->len);
+              function = NULL;
+            }
+          else if (missing_args > 0)
+            {
+              GskSlType *type = gsk_sl_expression_get_return_type (expression);
+              gsize provided = gsk_sl_constructor_get_args_by_type (type);
+
+              if (provided == 0)
+                {
+                  gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
+                                             "Invalid type %s for builtin constructor",
+                                             gsk_sl_type_get_name (type));
+                  function = NULL;
+                }
+              else
+                {
+                  missing_args -= MIN (missing_args, provided);
+                }
+            }
+
           token = gsk_sl_preprocessor_get (stream);
           if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
             break;
           gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
         }
 
+      if (missing_args > 0)
+        {
+          gsk_sl_preprocessor_error (stream, ARGUMENT_COUNT,
+                                     "Not enough arguments given to builtin constructor, %"G_GSIZE_FORMAT" 
are missing.",
+                                     missing_args);
+          function = NULL;
+        }
+
       call->n_arguments = arguments->len;
       call->arguments = (GskSlExpression **) g_ptr_array_free (arguments, FALSE);
     }
@@ -1313,7 +1369,7 @@ gsk_sl_expression_parse_function_call (GskSlScope        *scope,
   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 && !gsk_sl_function_matches (function, types, call->n_arguments, &error))
+  if (function && missing_args < 0 && !gsk_sl_function_matches (function, types, call->n_arguments, &error))
     {
       gsk_sl_preprocessor_emit_error (stream, TRUE, gsk_sl_preprocessor_get_location (stream), error);
       g_clear_error (&error);
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index 8d5f0eb..8192d09 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -80,62 +80,23 @@ gsk_sl_function_builtin_constructor_get_name (const GskSlFunction *function)
   return gsk_sl_type_get_name (builtin_constructor->type);
 }
 
-static void
-gsk_sl_function_builtin_constructor_print (const GskSlFunction *function,
-                                           GString             *string)
+static gsize
+gsk_sl_function_builtin_constructor_get_n_arguments (const GskSlFunction *function)
 {
+  return 0;
 }
 
-static guint
-gsk_sl_function_builtin_get_args_by_type (const GskSlType *type)
+static GskSlType *
+gsk_sl_function_builtin_constructor_get_argument_type (const GskSlFunction *function,
+                                                       gsize                i)
 {
-  if (gsk_sl_type_is_scalar (type))
-    return 1;
-  else if (gsk_sl_type_is_vector (type))
-    return gsk_sl_type_get_length (type);
-  else if (gsk_sl_type_is_matrix (type))
-    return gsk_sl_type_get_length (type) * gsk_sl_function_builtin_get_args_by_type 
(gsk_sl_type_get_index_type (type));
-  else
-    return 0;
+  return NULL;
 }
 
-static gboolean
-gsk_sl_function_builtin_constructor_matches (const GskSlFunction  *function,
-                                             GskSlType           **arguments,
-                                             gsize                 n_arguments,
-                                             GError              **error)
+static void
+gsk_sl_function_builtin_constructor_print (const GskSlFunction *function,
+                                           GString             *string)
 {
-  const GskSlFunctionBuiltinConstructor *builtin_constructor = (const GskSlFunctionBuiltinConstructor *) 
function;
-  guint needed, provided;
-  gsize i;
-
-  if (n_arguments == 1 && gsk_sl_type_is_scalar (arguments[0]))
-    return TRUE;
-
-  needed = gsk_sl_function_builtin_get_args_by_type (builtin_constructor->type);
-
-  for (i = 0; i < n_arguments; i++)
-    {
-      if (needed == 0)
-        {
-          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Too many arguments given to 
builtin_constructor, only the first %"G_GSIZE_FORMAT" are necessary.", i);
-          return FALSE;
-        }
-
-      provided = gsk_sl_function_builtin_get_args_by_type (arguments[i]);
-      if (provided == 0)
-        {
-          g_set_error (error,
-                       G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                       "Invalid type %s for builtin_constructor in argument %"G_GSIZE_FORMAT,
-                       gsk_sl_type_get_name (arguments[i]), i + 1);
-          return FALSE;
-        }
-
-      needed -= MIN (needed, provided);
-    }
-
-  return TRUE;
 }
 
 static guint32
@@ -149,8 +110,9 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_BUILTIN_CONSTRUCTOR = {
   gsk_sl_function_builtin_constructor_free,
   gsk_sl_function_builtin_constructor_get_return_type,
   gsk_sl_function_builtin_constructor_get_name,
+  gsk_sl_function_builtin_constructor_get_n_arguments,
+  gsk_sl_function_builtin_constructor_get_argument_type,
   gsk_sl_function_builtin_constructor_print,
-  gsk_sl_function_builtin_constructor_matches,
   gsk_sl_function_builtin_constructor_write_spv,
 };
 
@@ -190,47 +152,27 @@ gsk_sl_function_constructor_get_name (const GskSlFunction *function)
   return gsk_sl_type_get_name (constructor->type);
 }
 
-static void
-gsk_sl_function_constructor_print (const GskSlFunction *function,
-                                   GString             *string)
+static gsize
+gsk_sl_function_constructor_get_n_arguments (const GskSlFunction *function)
 {
+  const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
+
+  return gsk_sl_type_get_n_members (constructor->type);
 }
 
-static gboolean
-gsk_sl_function_constructor_matches (const GskSlFunction  *function,
-                                     GskSlType           **arguments,
-                                     gsize                 n_arguments,
-                                     GError              **error)
+static GskSlType *
+gsk_sl_function_constructor_get_argument_type (const GskSlFunction *function,
+                                               gsize                i)
 {
   const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
-  guint i;
-
-  if (n_arguments != gsk_sl_type_get_n_members (constructor->type))
-    {
-      g_set_error (error,
-                   GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
-                   "Constructor for %s needs %u arguments, but %"G_GSIZE_FORMAT" given.",
-                   gsk_sl_type_get_name (constructor->type),
-                   gsk_sl_type_get_n_members (constructor->type),
-                   n_arguments);
-      return FALSE;
-    }
 
-  for (i = 0; i < n_arguments; i++)
-    {
-      if (!gsk_sl_type_can_convert (gsk_sl_type_get_member_type (constructor->type, i), arguments[i]))
-        {
-          g_set_error (error,
-                       GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
-                       "Cannot convert argument %u from %s to %s.",
-                       i,
-                       gsk_sl_type_get_name (arguments[i]),
-                       gsk_sl_type_get_name (gsk_sl_type_get_member_type (constructor->type, i)));
-          return FALSE;
-        }
-    }
+  return gsk_sl_type_get_member_type (constructor->type, i);
+}
 
-  return TRUE;
+static void
+gsk_sl_function_constructor_print (const GskSlFunction *function,
+                                   GString             *string)
+{
 }
 
 static guint32
@@ -244,8 +186,9 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_CONSTRUCTOR = {
   gsk_sl_function_constructor_free,
   gsk_sl_function_constructor_get_return_type,
   gsk_sl_function_constructor_get_name,
+  gsk_sl_function_constructor_get_n_arguments,
+  gsk_sl_function_constructor_get_argument_type,
   gsk_sl_function_constructor_print,
-  gsk_sl_function_constructor_matches,
   gsk_sl_function_constructor_write_spv,
 };
 
@@ -299,6 +242,22 @@ gsk_sl_function_declared_get_name (const GskSlFunction *function)
   return declared->name;
 }
 
+static gsize
+gsk_sl_function_declared_get_n_arguments (const GskSlFunction *function)
+{
+  const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
+
+  return declared->n_arguments;
+}
+
+static GskSlType *
+gsk_sl_function_declared_get_argument_type (const GskSlFunction *function,
+                                            gsize                i)
+{
+  const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
+
+  return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declared->arguments[i]));
+}
 static void
 gsk_sl_function_declared_print (const GskSlFunction *function,
                                 GString             *string)
@@ -330,45 +289,6 @@ gsk_sl_function_declared_print (const GskSlFunction *function,
   g_string_append (string, "}\n");
 }
 
-static gboolean
-gsk_sl_function_declared_matches (const GskSlFunction  *function,
-                                  GskSlType           **arguments,
-                                  gsize                 n_arguments,
-                                  GError              **error)
-{
-  const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
-  guint i;
-
-  if (n_arguments != declared->n_arguments)
-    {
-      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.",
-                   declared->name, 
-                   declared->n_arguments,
-                   n_arguments);
-      return FALSE;
-    }
-
-  for (i = 0; i < n_arguments; i++)
-    {
-      GskSlType *type = gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declared->arguments[i]));
-
-      if (!gsk_sl_type_can_convert (type, arguments[i]))
-        {
-          g_set_error (error,
-                       GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
-                       "Cannot convert argument %u from %s to %s.",
-                       i,
-                       gsk_sl_type_get_name (arguments[i]),
-                       gsk_sl_type_get_name (type));
-          return FALSE;
-        }
-    }
-
-  return TRUE;
-}
-
 static guint32
 gsk_sl_function_declared_write_spv (const GskSlFunction *function,
                                     GskSpvWriter        *writer)
@@ -421,8 +341,9 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_DECLARED = {
   gsk_sl_function_declared_free,
   gsk_sl_function_declared_get_return_type,
   gsk_sl_function_declared_get_name,
+  gsk_sl_function_declared_get_n_arguments,
+  gsk_sl_function_declared_get_argument_type,
   gsk_sl_function_declared_print,
-  gsk_sl_function_declared_matches,
   gsk_sl_function_declared_write_spv,
 };
 
@@ -609,6 +530,12 @@ gsk_sl_function_unref (GskSlFunction *function)
   function->class->free (function);
 }
 
+gboolean
+gsk_sl_function_is_builtin_constructor (const GskSlFunction *function)
+{
+  return function->class == &GSK_SL_FUNCTION_BUILTIN_CONSTRUCTOR;
+}
+
 GskSlType *
 gsk_sl_function_get_return_type (const GskSlFunction *function)
 {
@@ -621,6 +548,19 @@ gsk_sl_function_get_name (const GskSlFunction *function)
   return function->class->get_name (function);
 }
 
+gsize
+gsk_sl_function_get_n_arguments (const GskSlFunction *function)
+{
+  return function->class->get_n_arguments (function);
+}
+
+GskSlType *
+gsk_sl_function_get_argument_type (const GskSlFunction *function,
+                                   gsize                i)
+{
+  return function->class->get_argument_type (function, i);
+}
+
 void
 gsk_sl_function_print (const GskSlFunction *function,
                        GString             *string)
@@ -634,7 +574,34 @@ gsk_sl_function_matches (const GskSlFunction  *function,
                          gsize                 n_arguments,
                          GError              **error)
 {
-  return function->class->matches (function, arguments, n_arguments, error);
+  guint i;
+
+  if (n_arguments != gsk_sl_function_get_n_arguments (function))
+    {
+      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;
+    }
+
+  for (i = 0; i < n_arguments; i++)
+    {
+      if (!gsk_sl_type_can_convert (gsk_sl_function_get_argument_type (function, i), arguments[i]))
+        {
+          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;
+        }
+    }
+
+  return TRUE;
 }
 
 guint32
diff --git a/gsk/gskslfunctionprivate.h b/gsk/gskslfunctionprivate.h
index 9e28374..ce38b8e 100644
--- a/gsk/gskslfunctionprivate.h
+++ b/gsk/gskslfunctionprivate.h
@@ -39,12 +39,11 @@ struct _GskSlFunctionClass {
 
   GskSlType *           (* get_return_type)                     (const GskSlFunction    *function);
   const char *          (* get_name)                            (const GskSlFunction    *function);
+  gsize                 (* get_n_arguments)                     (const GskSlFunction    *function);
+  GskSlType *           (* get_argument_type)                   (const GskSlFunction    *function,
+                                                                 gsize                   i);
   void                  (* print)                               (const GskSlFunction    *function,
                                                                  GString                *string);
-  gboolean              (* matches)                             (const GskSlFunction    *function,
-                                                                 GskSlType             **arguments,
-                                                                 gsize                   n_arguments,
-                                                                 GError                **error);
   guint32               (* write_spv)                           (const GskSlFunction    *function,
                                                                  GskSpvWriter           *writer);
 };
@@ -58,11 +57,16 @@ GskSlFunction *         gsk_sl_function_new_parse               (GskSlScope
 GskSlFunction *         gsk_sl_function_ref                     (GskSlFunction          *function);
 void                    gsk_sl_function_unref                   (GskSlFunction          *function);
 
+gboolean                gsk_sl_function_is_builtin_constructor  (const GskSlFunction    *function);
+
 void                    gsk_sl_function_print                   (const GskSlFunction    *function,
                                                                  GString                *string);
 
 const char *            gsk_sl_function_get_name                (const GskSlFunction    *function);
 GskSlType *             gsk_sl_function_get_return_type         (const GskSlFunction    *function);
+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,


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