[gtk+/wip/otte/shader: 152/226] gskslexpression: Add gsk_sl_expression_is_assignable()



commit bda72e2c2338e7cb34e387380ccfd779abae14f2
Author: Benjamin Otte <otte redhat com>
Date:   Sun Oct 8 06:46:57 2017 +0200

    gskslexpression: Add gsk_sl_expression_is_assignable()
    
    And use it to fail when parsing assignments.

 gsk/gskslexpression.c        |  109 +++++++++++++++++++++++++++++++++++++++--
 gsk/gskslexpressionprivate.h |    2 +
 2 files changed, 105 insertions(+), 6 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 3af2a75..4238d25 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -46,6 +46,8 @@ struct _GskSlExpressionClass {
 
   void                  (* print)                               (const GskSlExpression  *expression,
                                                                  GskSlPrinter           *printer);
+  gboolean              (* is_assignable)                       (const GskSlExpression  *expression,
+                                                                 GError                **error);
   GskSlType *           (* get_return_type)                     (const GskSlExpression  *expression);
   GskSlValue *          (* get_constant)                        (const GskSlExpression  *expression);
   guint32               (* write_spv)                           (const GskSlExpression  *expression,
@@ -67,6 +69,18 @@ gsk_sl_expression_alloc (const GskSlExpressionClass *klass,
 }
 #define gsk_sl_expression_new(_name, _klass) ((_name *) gsk_sl_expression_alloc ((_klass), sizeof (_name)))
 
+static gboolean
+gsk_sl_expression_default_is_assignable (const GskSlExpression  *expression,
+                                         GError                **error)
+{
+  g_set_error (error,
+               GSK_SL_COMPILER_ERROR,
+               GSK_SL_COMPILER_ERROR_SYNTAX,
+               "Assignment requires l-value.");
+                   
+  return FALSE;
+}
+
 /* ASSIGNMENT */
 
 typedef struct _GskSlExpressionAssignment GskSlExpressionAssignment;
@@ -130,6 +144,7 @@ gsk_sl_expression_assignment_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_ASSIGNMENT = {
   gsk_sl_expression_assignment_free,
   gsk_sl_expression_assignment_print,
+  gsk_sl_expression_default_is_assignable,
   gsk_sl_expression_assignment_get_return_type,
   gsk_sl_expression_assignment_get_constant,
   gsk_sl_expression_assignment_write_spv
@@ -221,6 +236,7 @@ gsk_sl_expression_binary_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_BINARY = {
   gsk_sl_expression_binary_free,
   gsk_sl_expression_binary_print,
+  gsk_sl_expression_default_is_assignable,
   gsk_sl_expression_binary_get_return_type,
   gsk_sl_expression_binary_get_constant,
   gsk_sl_expression_binary_write_spv
@@ -255,6 +271,24 @@ gsk_sl_expression_reference_print (const GskSlExpression *expression,
   gsk_sl_printer_append (printer, gsk_sl_variable_get_name (reference->variable));
 }
 
+static gboolean
+gsk_sl_expression_reference_is_assignable (const GskSlExpression  *expression,
+                                           GError                **error)
+{
+  const GskSlExpressionReference *reference = (const GskSlExpressionReference *) expression;
+
+  if (gsk_sl_variable_is_constant (reference->variable))
+    {
+      g_set_error (error,
+                   GSK_SL_COMPILER_ERROR,
+                   GSK_SL_COMPILER_ERROR_CONSTANT,
+                   "Cannot assign constant \"%s\".", gsk_sl_variable_get_name (reference->variable));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 static GskSlType *
 gsk_sl_expression_reference_get_return_type (const GskSlExpression *expression)
 {
@@ -294,6 +328,7 @@ gsk_sl_expression_reference_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_REFERENCE = {
   gsk_sl_expression_reference_free,
   gsk_sl_expression_reference_print,
+  gsk_sl_expression_reference_is_assignable,
   gsk_sl_expression_reference_get_return_type,
   gsk_sl_expression_reference_get_constant,
   gsk_sl_expression_reference_write_spv
@@ -670,6 +705,7 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTRUCTOR = {
   gsk_sl_expression_constructor_free,
   gsk_sl_expression_constructor_print,
+  gsk_sl_expression_default_is_assignable,
   gsk_sl_expression_constructor_get_return_type,
   gsk_sl_expression_constructor_get_constant,
   gsk_sl_expression_constructor_write_spv
@@ -786,6 +822,7 @@ gsk_sl_expression_function_call_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = {
   gsk_sl_expression_function_call_free,
   gsk_sl_expression_function_call_print,
+  gsk_sl_expression_default_is_assignable,
   gsk_sl_expression_function_call_get_return_type,
   gsk_sl_expression_function_call_get_constant,
   gsk_sl_expression_function_call_write_spv
@@ -823,6 +860,15 @@ gsk_sl_expression_member_print (const GskSlExpression *expression,
   gsk_sl_printer_append (printer, gsk_sl_type_get_member_name (gsk_sl_expression_get_return_type 
(member->expr), member->id));
 }
 
+static gboolean
+gsk_sl_expression_member_is_assignable (const GskSlExpression  *expression,
+                                        GError                **error)
+{
+  const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
+
+  return gsk_sl_expression_is_assignable (member->expr, error);
+}
+
 static GskSlType *
 gsk_sl_expression_member_get_return_type (const GskSlExpression *expression)
 {
@@ -867,6 +913,7 @@ gsk_sl_expression_member_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_MEMBER = {
   gsk_sl_expression_member_free,
   gsk_sl_expression_member_print,
+  gsk_sl_expression_member_is_assignable,
   gsk_sl_expression_member_get_return_type,
   gsk_sl_expression_member_get_constant,
   gsk_sl_expression_member_write_spv
@@ -918,6 +965,42 @@ gsk_sl_expression_swizzle_print (const GskSlExpression *expression,
     }
 }
 
+static gboolean
+gsk_sl_expression_swizzle_is_assignable (const GskSlExpression  *expression,
+                                         GError                **error)
+{
+  const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+
+  if (!gsk_sl_expression_is_assignable (swizzle->expr, error))
+    return FALSE;
+
+  switch (swizzle->length)
+  {
+    default:
+      g_assert_not_reached ();
+    case 4:
+      if (swizzle->indexes[0] == swizzle->indexes[3] ||
+          swizzle->indexes[1] == swizzle->indexes[3] ||
+          swizzle->indexes[2] == swizzle->indexes[3])
+        break;
+    case 3:
+      if (swizzle->indexes[0] == swizzle->indexes[2] ||
+          swizzle->indexes[1] == swizzle->indexes[2])
+        break;
+    case 2:
+      if (swizzle->indexes[0] == swizzle->indexes[1])
+        break;
+    case 1:
+      return TRUE;
+  }
+  
+  g_set_error (error,
+               GSK_SL_COMPILER_ERROR,
+               GSK_SL_COMPILER_ERROR_SYNTAX,
+               "Cannot assign to swizzle with duplicate components.");
+  return FALSE;
+}
+
 static GskSlType *
 gsk_sl_expression_swizzle_get_return_type (const GskSlExpression *expression)
 {
@@ -1022,6 +1105,7 @@ gsk_sl_expression_swizzle_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_SWIZZLE = {
   gsk_sl_expression_swizzle_free,
   gsk_sl_expression_swizzle_print,
+  gsk_sl_expression_swizzle_is_assignable,
   gsk_sl_expression_swizzle_get_return_type,
   gsk_sl_expression_swizzle_get_constant,
   gsk_sl_expression_swizzle_write_spv
@@ -1144,6 +1228,7 @@ gsk_sl_expression_negation_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_NEGATION = {
   gsk_sl_expression_negation_free,
   gsk_sl_expression_negation_print,
+  gsk_sl_expression_default_is_assignable,
   gsk_sl_expression_negation_get_return_type,
   gsk_sl_expression_negation_get_constant,
   gsk_sl_expression_negation_write_spv
@@ -1206,6 +1291,7 @@ gsk_sl_expression_constant_write_spv (const GskSlExpression *expression,
 static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTANT = {
   gsk_sl_expression_constant_free,
   gsk_sl_expression_constant_print,
+  gsk_sl_expression_default_is_assignable,
   gsk_sl_expression_constant_get_return_type,
   gsk_sl_expression_constant_get_constant,
   gsk_sl_expression_constant_write_spv
@@ -2331,6 +2417,7 @@ gsk_sl_expression_parse_assignment (GskSlScope        *scope,
   GskSlExpression *lvalue, *rvalue;
   GskSlExpressionAssignment *assign;
   GskSlType *result_type;
+  GError *error = NULL;
 
   lvalue = gsk_sl_expression_parse_conditional (scope, preproc);
 
@@ -2354,18 +2441,21 @@ gsk_sl_expression_parse_assignment (GskSlScope        *scope,
         return lvalue;
   }
 
-#if 0
-  if (gsk_sl_expression_is_constant (lvalue))
+  if (!gsk_sl_expression_is_assignable (lvalue, &error))
     {
-      gsk_sl_preprocessor_error (stream, "Cannot assign to a return lvalue.");
+      gsk_sl_preprocessor_emit_error (preproc,
+                                      TRUE,
+                                      gsk_sl_preprocessor_get_location (preproc),
+                                      error);
+
+      g_clear_error (&error);
 
       /* Continue parsing like normal here to get more errors */
-      gsk_sl_preprocessor_consume (stream, lvalue);
+      gsk_sl_preprocessor_consume (preproc, lvalue);
       gsk_sl_expression_unref (lvalue);
 
-      return gsk_sl_expression_parse_assignment (scope, stream);
+      return gsk_sl_expression_parse_assignment (scope, preproc);
     }
-#endif
 
   binary = gsk_sl_binary_get_for_token (token->type);
   gsk_sl_preprocessor_consume (preproc, NULL);
@@ -2442,6 +2532,13 @@ gsk_sl_expression_print (const GskSlExpression *expression,
   expression->class->print (expression, printer);
 }
 
+gboolean
+gsk_sl_expression_is_assignable (const GskSlExpression  *expression,
+                                 GError                **error)
+{
+  return expression->class->is_assignable (expression, error);
+}
+
 GskSlType *
 gsk_sl_expression_get_return_type (const GskSlExpression *expression)
 {
diff --git a/gsk/gskslexpressionprivate.h b/gsk/gskslexpressionprivate.h
index 0247ad6..d9dc7a3 100644
--- a/gsk/gskslexpressionprivate.h
+++ b/gsk/gskslexpressionprivate.h
@@ -41,6 +41,8 @@ void                    gsk_sl_expression_unref                 (GskSlExpression
 
 void                    gsk_sl_expression_print                 (const GskSlExpression  *expression,
                                                                  GskSlPrinter           *printer);
+gboolean                gsk_sl_expression_is_assignable         (const GskSlExpression  *expression,
+                                                                 GError                **error);
 GskSlType *             gsk_sl_expression_get_return_type       (const GskSlExpression  *expression);
 GskSlValue *            gsk_sl_expression_get_constant          (const GskSlExpression  *expression);
 


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