[gtk+/wip/otte/shader: 3/33] gskslnode: Add support for bitwise operations



commit eeb583019ac0e87c1dec65a63b3b6d90ebf5a624
Author: Benjamin Otte <otte redhat com>
Date:   Sun Sep 17 15:51:42 2017 +0200

    gskslnode: Add support for bitwise operations
    
    Includes lots of new API for inspecting types that is necessary to do
    compile time checks.

 gsk/gskslnode.c        |  224 ++++++++++++++++++++++++++++++++++++++++++++++--
 gsk/gsksltype.c        |   57 ++++++++++++-
 gsk/gsksltypeprivate.h |    5 +
 3 files changed, 276 insertions(+), 10 deletions(-)
---
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index 35fd953..43686a9 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -350,18 +350,89 @@ gsk_sl_node_operation_print (GskSlNode *node,
 }
 
 static GskSlType *
-gsk_sl_node_operation_get_return_type (GskSlNode *node)
+gsk_sl_node_bitwise_type_check (GskSlPreprocessor *stream,
+                                GskSlType         *ltype,
+                                GskSlType         *rtype)
 {
-  GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
-  GskSlType *ltype, *rtype;
+  GskSlScalarType lscalar, rscalar;
 
-  ltype = gsk_sl_node_get_return_type (operation->left);
-  rtype = gsk_sl_node_get_return_type (operation->right);
+  lscalar = gsk_sl_type_get_scalar_type (ltype);
+  if (lscalar != GSK_SL_INT && lscalar != GSK_SL_UINT)
+    {
+      if (stream)
+        gsk_sl_preprocessor_error (stream, "Left operand is not an integer type.");
+      return NULL;
+    }
+  rscalar = gsk_sl_type_get_scalar_type (ltype);
+  if (rscalar != GSK_SL_INT && rscalar != GSK_SL_UINT)
+    {
+      if (stream)
+        gsk_sl_preprocessor_error (stream, "Right operand is not an integer type.");
+      return NULL;
+    }
+  if (!gsk_sl_type_is_scalar (ltype) && !gsk_sl_type_is_vector (ltype))
+    {
+      if (stream)
+        gsk_sl_preprocessor_error (stream, "Left operand is neither a scalar nor a vector.");
+      return NULL;
+    }
+  if (!gsk_sl_type_is_scalar (rtype) && !gsk_sl_type_is_vector (rtype))
+    {
+      if (stream)
+        gsk_sl_preprocessor_error (stream, "Right operand is neither a scalar nor a vector.");
+      return NULL;
+    }
+  if (gsk_sl_type_is_vector (ltype) && gsk_sl_type_is_vector (rtype) &&
+      gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
+    {
+      if (stream)
+        gsk_sl_preprocessor_error (stream, "Vector operands do not have the same length.");
+      return NULL;
+    }
 
-  if (gsk_sl_type_can_convert (ltype, rtype))
-    return ltype;
+  rscalar = lscalar == GSK_SL_UINT ? GSK_SL_UINT : rscalar;
+  if (gsk_sl_type_is_scalar (ltype) && gsk_sl_type_is_scalar (rtype))
+    return gsk_sl_type_get_scalar (rscalar);
   else
-    return rtype;
+    return gsk_sl_type_get_vector (rscalar, gsk_sl_type_get_length (ltype));
+}
+
+static GskSlType *
+gsk_sl_node_operation_get_return_type (GskSlNode *node)
+{
+  GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
+
+  switch (operation->op)
+  {
+    case GSK_SL_OPERATION_MUL:
+    case GSK_SL_OPERATION_DIV:
+    case GSK_SL_OPERATION_MOD:
+    case GSK_SL_OPERATION_ADD:
+    case GSK_SL_OPERATION_SUB:
+    case GSK_SL_OPERATION_LSHIFT:
+    case GSK_SL_OPERATION_RSHIFT:
+    case GSK_SL_OPERATION_LESS:
+    case GSK_SL_OPERATION_GREATER:
+    case GSK_SL_OPERATION_LESS_EQUAL:
+    case GSK_SL_OPERATION_GREATER_EQUAL:
+    case GSK_SL_OPERATION_EQUAL:
+    case GSK_SL_OPERATION_NOT_EQUAL:
+      g_assert_not_reached ();
+      return NULL;
+    case GSK_SL_OPERATION_AND:
+    case GSK_SL_OPERATION_XOR:
+    case GSK_SL_OPERATION_OR:
+      return gsk_sl_node_bitwise_type_check (NULL,
+                                             gsk_sl_node_get_return_type (operation->left),
+                                             gsk_sl_node_get_return_type (operation->right));
+    case GSK_SL_OPERATION_LOGICAL_AND:
+    case GSK_SL_OPERATION_LOGICAL_XOR:
+    case GSK_SL_OPERATION_LOGICAL_OR:
+      return gsk_sl_type_get_scalar (GSK_SL_BOOL);
+    default:
+      g_assert_not_reached ();
+      return NULL;
+  }
 }
 
 static gboolean
@@ -712,11 +783,146 @@ gsk_sl_node_parse_primary_expression (GskSlNodeProgram  *program,
 }
 
 static GskSlNode *
+gsk_sl_node_parse_equality_expression (GskSlNodeProgram  *program,
+                                       GskSlScope        *scope,
+                                       GskSlPreprocessor *stream)
+{
+  return gsk_sl_node_parse_primary_expression (program, scope, stream);
+}
+
+static GskSlNode *
+gsk_sl_node_parse_and_expression (GskSlNodeProgram  *program,
+                                  GskSlScope        *scope,
+                                  GskSlPreprocessor *stream)
+{
+  const GskSlToken *token;
+  GskSlNode *node;
+  GskSlNodeOperation *operation;
+
+  node = gsk_sl_node_parse_equality_expression (program, scope, stream);
+  if (node == NULL)
+    return NULL;
+
+  while (TRUE)
+    {
+      token = gsk_sl_preprocessor_get (stream);
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_AMPERSAND))
+        return node;
+
+      operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
+      operation->left = node;
+      operation->op = GSK_SL_OPERATION_AND;
+      gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
+      operation->right = gsk_sl_node_parse_equality_expression (program, scope, stream);
+      if (operation->right == NULL)
+        {
+          gsk_sl_node_ref (node);
+          gsk_sl_node_unref ((GskSlNode *) operation);
+        }
+      else if (!gsk_sl_node_bitwise_type_check (stream,
+                                                gsk_sl_node_get_return_type (operation->left),
+                                                gsk_sl_node_get_return_type (operation->right)))
+        {
+          gsk_sl_node_ref (node);
+          gsk_sl_node_unref ((GskSlNode *) operation);
+        }
+      else
+        {
+          node = (GskSlNode *) operation;
+        }
+    }
+
+  return node;
+}
+
+static GskSlNode *
+gsk_sl_node_parse_xor_expression (GskSlNodeProgram  *program,
+                                  GskSlScope        *scope,
+                                  GskSlPreprocessor *stream)
+{
+  const GskSlToken *token;
+  GskSlNode *node;
+  GskSlNodeOperation *operation;
+
+  node = gsk_sl_node_parse_and_expression (program, scope, stream);
+  if (node == NULL)
+    return NULL;
+
+  while (TRUE)
+    {
+      token = gsk_sl_preprocessor_get (stream);
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_CARET))
+        return node;
+
+      operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
+      operation->left = node;
+      operation->op = GSK_SL_OPERATION_XOR;
+      gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
+      operation->right = gsk_sl_node_parse_and_expression (program, scope, stream);
+      if (operation->right == NULL)
+        {
+          gsk_sl_node_ref (node);
+          gsk_sl_node_unref ((GskSlNode *) operation);
+        }
+      else if (!gsk_sl_node_bitwise_type_check (stream,
+                                                gsk_sl_node_get_return_type (operation->left),
+                                                gsk_sl_node_get_return_type (operation->right)))
+        {
+          gsk_sl_node_ref (node);
+          gsk_sl_node_unref ((GskSlNode *) operation);
+        }
+      else
+        {
+          node = (GskSlNode *) operation;
+        }
+    }
+
+  return node;
+}
+
+static GskSlNode *
 gsk_sl_node_parse_or_expression (GskSlNodeProgram  *program,
                                  GskSlScope        *scope,
                                  GskSlPreprocessor *stream)
 {
-  return gsk_sl_node_parse_primary_expression (program, scope, stream);
+  const GskSlToken *token;
+  GskSlNode *node;
+  GskSlNodeOperation *operation;
+
+  node = gsk_sl_node_parse_xor_expression (program, scope, stream);
+  if (node == NULL)
+    return NULL;
+
+  while (TRUE)
+    {
+      token = gsk_sl_preprocessor_get (stream);
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_VERTICAL_BAR))
+        return node;
+
+      operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
+      operation->left = node;
+      operation->op = GSK_SL_OPERATION_OR;
+      gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
+      operation->right = gsk_sl_node_parse_xor_expression (program, scope, stream);
+      if (operation->right == NULL)
+        {
+          gsk_sl_node_ref (node);
+          gsk_sl_node_unref ((GskSlNode *) operation);
+        }
+      else if (!gsk_sl_node_bitwise_type_check (stream,
+                                                gsk_sl_node_get_return_type (operation->left),
+                                                gsk_sl_node_get_return_type (operation->right)))
+        {
+          gsk_sl_node_ref (node);
+          gsk_sl_node_unref ((GskSlNode *) operation);
+        }
+      else
+        {
+          node = (GskSlNode *) operation;
+        }
+    }
+
+  return node;
 }
 
 static GskSlNode *
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index e7790ab..8e3e8e5 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -42,6 +42,7 @@ struct _GskSlTypeClass {
   void                  (* print)                               (GskSlType           *type,
                                                                  GString             *string);
   GskSlScalarType       (* get_scalar_type)                     (GskSlType           *type);
+  guint                 (* get_length)                          (GskSlType           *type);
   gboolean              (* can_convert)                         (GskSlType           *target,
                                                                  GskSlType           *source);
 };
@@ -125,6 +126,12 @@ gsk_sl_type_scalar_get_scalar_type (GskSlType *type)
   return scalar->scalar;
 }
 
+static guint
+gsk_sl_type_scalar_get_length (GskSlType *type)
+{
+  return 0;
+}
+
 static gboolean
 gsk_sl_type_scalar_can_convert (GskSlType *target,
                                 GskSlType *source)
@@ -142,6 +149,7 @@ static const GskSlTypeClass GSK_SL_TYPE_SCALAR = {
   gsk_sl_type_scalar_free,
   gsk_sl_type_scalar_print,
   gsk_sl_type_scalar_get_scalar_type,
+  gsk_sl_type_scalar_get_length,
   gsk_sl_type_scalar_can_convert
 };
 
@@ -202,6 +210,14 @@ gsk_sl_type_vector_get_scalar_type (GskSlType *type)
   return vector->scalar;
 }
 
+static guint
+gsk_sl_type_vector_get_length (GskSlType *type)
+{
+  GskSlTypeVector *vector = (GskSlTypeVector *) type;
+
+  return vector->length;
+}
+
 static gboolean
 gsk_sl_type_vector_can_convert (GskSlType *target,
                                 GskSlType *source)
@@ -222,6 +238,7 @@ static const GskSlTypeClass GSK_SL_TYPE_VECTOR = {
   gsk_sl_type_vector_free,
   gsk_sl_type_vector_print,
   gsk_sl_type_vector_get_scalar_type,
+  gsk_sl_type_vector_get_length,
   gsk_sl_type_vector_can_convert
 };
 
@@ -265,6 +282,14 @@ gsk_sl_type_matrix_get_scalar_type (GskSlType *type)
   return matrix->scalar;
 }
 
+static guint
+gsk_sl_type_matrix_get_length (GskSlType *type)
+{
+  GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
+
+  return matrix->columns;
+}
+
 static gboolean
 gsk_sl_type_matrix_can_convert (GskSlType *target,
                                 GskSlType *source)
@@ -286,6 +311,7 @@ static const GskSlTypeClass GSK_SL_TYPE_MATRIX = {
   gsk_sl_type_matrix_free,
   gsk_sl_type_matrix_print,
   gsk_sl_type_matrix_get_scalar_type,
+  gsk_sl_type_matrix_get_length,
   gsk_sl_type_matrix_can_convert
 };
 
@@ -585,9 +611,38 @@ gsk_sl_type_to_string (const GskSlType *type)
 }
 
 gboolean
+gsk_sl_type_is_scalar (const GskSlType *type)
+{
+  return type->class == &GSK_SL_TYPE_SCALAR;
+}
+
+gboolean
+gsk_sl_type_is_vector (const GskSlType *type)
+{
+  return type->class == &GSK_SL_TYPE_VECTOR;
+}
+
+gboolean
+gsk_sl_type_is_matrix (const GskSlType *type)
+{
+  return type->class == &GSK_SL_TYPE_MATRIX;
+}
+
+GskSlScalarType
+gsk_sl_type_get_scalar_type (const GskSlType *type)
+{
+  return type->class->get_scalar_type (type);
+}
+
+GskSlScalarType
+gsk_sl_type_get_length (const GskSlType *type)
+{
+  return type->class->get_length (type);
+}
+
+gboolean
 gsk_sl_type_can_convert (const GskSlType *target,
                          const GskSlType *source)
 {
   return target->class->can_convert (target, source);
 }
-
diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h
index ff208d2..b7166ac 100644
--- a/gsk/gsksltypeprivate.h
+++ b/gsk/gsksltypeprivate.h
@@ -49,6 +49,11 @@ void                    gsk_sl_type_print                       (const GskSlType
                                                                  GString             *string);
 char *                  gsk_sl_type_to_string                   (const GskSlType     *type);
 
+gboolean                gsk_sl_type_is_scalar                   (const GskSlType     *type);
+gboolean                gsk_sl_type_is_vector                   (const GskSlType     *type);
+gboolean                gsk_sl_type_is_matrix                   (const GskSlType     *type);
+GskSlScalarType         gsk_sl_type_get_scalar_type             (const GskSlType     *type);
+guint                   gsk_sl_type_get_length                  (const GskSlType     *type);
 gboolean                gsk_sl_type_can_convert                 (const GskSlType     *target,
                                                                  const GskSlType     *source);
 


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