[gtk+/wip/otte/shader: 18/48] gskslfunction: Parse arguments



commit 5953f1cacad8875a2aeef1b9d40edbc3fd27f462
Author: Benjamin Otte <otte redhat com>
Date:   Thu Sep 28 23:11:34 2017 +0200

    gskslfunction: Parse arguments

 gsk/gskslfunction.c |  111 ++++++++++++++++++++++++++++++++++++++++++++++++--
 gsk/gskslnode.c     |    9 +++-
 2 files changed, 113 insertions(+), 7 deletions(-)
---
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index dd91425..b841579 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -21,10 +21,12 @@
 #include "gskslfunctionprivate.h"
 
 #include "gskslnodeprivate.h"
+#include "gskslpointertypeprivate.h"
 #include "gskslpreprocessorprivate.h"
 #include "gskslscopeprivate.h"
 #include "gsksltokenizerprivate.h"
 #include "gsksltypeprivate.h"
+#include "gskslvariableprivate.h"
 #include "gskspvwriterprivate.h"
 
 static GskSlFunction *
@@ -220,6 +222,8 @@ struct _GskSlFunctionDeclared {
   GskSlScope *scope;
   GskSlType *return_type;
   char *name;
+  GskSlVariable **arguments;
+  gsize n_arguments;
   GSList *statements;
 };
 
@@ -227,7 +231,11 @@ static void
 gsk_sl_function_declared_free (GskSlFunction *function)
 {
   GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
+  guint i;
 
+  for (i = 0; i < declared->n_arguments; i++)
+    gsk_sl_variable_unref (declared->arguments[i]);
+  g_free (declared->arguments);
   if (declared->scope)
     gsk_sl_scope_unref (declared->scope);
   if (declared->return_type)
@@ -260,12 +268,19 @@ gsk_sl_function_declared_print (const GskSlFunction *function,
 {
   const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
   GSList *l;
+  guint i;
 
   g_string_append (string, gsk_sl_type_get_name (declared->return_type));
   g_string_append (string, "\n");
 
   g_string_append (string, declared->name);
   g_string_append (string, " (");
+  for (i = 0; i < declared->n_arguments; i++)
+    {
+      if (i > 0)
+        g_string_append (string, ", ");
+      gsk_sl_variable_print (declared->arguments[i], string);
+    }
   g_string_append (string, ")\n");
 
   g_string_append (string, "{\n");
@@ -284,10 +299,34 @@ gsk_sl_function_declared_matches (const GskSlFunction  *function,
                                   gsize                 n_arguments,
                                   GError              **error)
 {
-  if (n_arguments > 0)
+  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++)
     {
-       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Function only takes %u arguments.", 0);
-       return FALSE;
+      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;
@@ -385,9 +424,73 @@ gsk_sl_function_new_parse (GskSlScope        *scope,
     }
   gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
 
+  function->scope = gsk_sl_scope_new (scope, function->return_type);
+
   token = gsk_sl_preprocessor_get (preproc);
   if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
     {
+      GPtrArray *arguments = g_ptr_array_new ();
+
+      while (TRUE)
+        {
+          GskSlDecorations decoration;
+          GskSlType *type;
+          GskSlVariable *variable;
+
+          gsk_sl_decoration_list_parse (scope,
+                                        preproc,
+                                        &decoration);
+
+          type = gsk_sl_type_new_parse (scope, preproc);
+
+          token = gsk_sl_preprocessor_get (preproc);
+          if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+            {
+              GskSlPointerType *pointer_type;
+              guint i;
+
+              if (gsk_sl_scope_lookup_variable (function->scope, token->str))
+                {
+                  for (i = 0; i < function->n_arguments; i++)
+                    {
+                      if (g_str_equal (gsk_sl_variable_get_name (g_ptr_array_index (arguments, i)), 
token->str))
+                        {
+                          gsk_sl_preprocessor_error (preproc, DECLARATION, "Duplicate argument name 
\"%s\".", token->str);
+                          break;
+                        }
+                    }
+                  if (i == arguments->len)
+                    gsk_sl_preprocessor_warn (preproc, SHADOW, "Function argument \"%s\" shadows global 
variable of same name.", token->str);
+                }
+
+              pointer_type = gsk_sl_pointer_type_new (type, TRUE, 
decoration.values[GSK_SL_DECORATION_CALLER_ACCESS].value);
+              variable = gsk_sl_variable_new (pointer_type, g_strdup (token->str), NULL, 
decoration.values[GSK_SL_DECORATION_CONST].set);
+              gsk_sl_pointer_type_unref (pointer_type);
+              g_ptr_array_add (arguments, variable);
+              
+              gsk_sl_scope_add_variable (function->scope, variable);
+              gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
+            }
+          else
+            {
+              gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected an identifier as the variable name.");
+            }
+
+          gsk_sl_type_unref (type);
+
+          token = gsk_sl_preprocessor_get (preproc);
+          if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
+            break;
+
+          gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
+        }
+
+      function->n_arguments = arguments->len;
+      function->arguments = (GskSlVariable **) g_ptr_array_free (arguments, FALSE);
+    }
+
+  if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
+    {
       gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected a closing \")\"");
       gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_PAREN);
     }
@@ -407,8 +510,6 @@ gsk_sl_function_new_parse (GskSlScope        *scope,
     }
   gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
 
-  function->scope = gsk_sl_scope_new (scope, function->return_type);
-
   for (token = gsk_sl_preprocessor_get (preproc);
        !gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE) && !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
        token = gsk_sl_preprocessor_get (preproc))
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index 9eb5574..0e48d2e 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -382,11 +382,11 @@ gsk_sl_node_parse_statement (GskSlScope        *scope,
     case GSK_SL_TOKEN_DMAT4X3:
     case GSK_SL_TOKEN_DMAT4X4:
     case GSK_SL_TOKEN_STRUCT:
-    case GSK_SL_TOKEN_IDENTIFIER:
       {
         GskSlType *type;
         GskSlDecorations decoration;
 
+its_a_type:
         gsk_sl_decoration_list_parse (scope,
                                       preproc,
                                       &decoration);
@@ -458,10 +458,15 @@ gsk_sl_node_parse_statement (GskSlScope        *scope,
         }
       break;
 
+    case GSK_SL_TOKEN_IDENTIFIER:
+      if (gsk_sl_scope_lookup_type (scope, token->str))
+        goto its_a_type;
+      /* else fall through*/
+
     default:
       {
         GskSlNodeExpression *node_expression;
-            
+
         node_expression = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
         node_expression->expression = gsk_sl_expression_parse (scope, preproc);
 


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