[gtk+/wip/otte/shader: 39/98] gskslexpression: Move GskSlExpressionOperation to binaries



commit 0c90b1362496e1c6f495b412694784c5273319ae
Author: Benjamin Otte <otte redhat com>
Date:   Sun Oct 8 05:05:41 2017 +0200

    gskslexpression: Move GskSlExpressionOperation to binaries
    
    All those operations are now unimplemented binary types.

 gsk/gskslbinary.c     |  316 ++++++++++++++++++++++-
 gsk/gskslexpression.c |  703 ++++++++++++++++---------------------------------
 2 files changed, 536 insertions(+), 483 deletions(-)
---
diff --git a/gsk/gskslbinary.c b/gsk/gskslbinary.c
index e7a2f71..01296d4 100644
--- a/gsk/gskslbinary.c
+++ b/gsk/gskslbinary.c
@@ -742,6 +742,169 @@ static const GskSlBinary GSK_SL_BINARY_DIVISION = {
 
 /* UNIMPLEMENTED */
 
+static GskSlType *
+gsk_sl_bitwise_check_type (GskSlPreprocessor *preproc,
+                           GskSlType         *ltype,
+                           GskSlType         *rtype)
+{
+  GskSlScalarType lscalar, rscalar;
+
+  lscalar = gsk_sl_type_get_scalar_type (ltype);
+  if (lscalar != GSK_SL_INT && lscalar != GSK_SL_UINT)
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand %s is not an integer type.", 
gsk_sl_type_get_name (ltype));
+      return NULL;
+    }
+  rscalar = gsk_sl_type_get_scalar_type (ltype);
+  if (rscalar != GSK_SL_INT && rscalar != GSK_SL_UINT)
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand %s is not an integer type.", 
gsk_sl_type_get_name (rtype));
+      return NULL;
+    }
+  if (!gsk_sl_type_is_scalar (ltype) && !gsk_sl_type_is_vector (ltype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (ltype));
+      return NULL;
+    }
+  if (!gsk_sl_type_is_scalar (rtype) && !gsk_sl_type_is_vector (rtype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (rtype));
+      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))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+                                 "Vector operands %s and %s do not have the same length.",
+                                 gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
+      return NULL;
+    }
+
+  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 gsk_sl_type_get_vector (rscalar, gsk_sl_type_get_length (ltype));
+}
+
+static GskSlType *
+gsk_sl_shift_check_type (GskSlPreprocessor *preproc,
+                         GskSlType         *ltype,
+                         GskSlType         *rtype)
+{
+  GskSlScalarType lscalar, rscalar;
+
+  lscalar = gsk_sl_type_get_scalar_type (ltype);
+  if (lscalar != GSK_SL_INT && lscalar != GSK_SL_UINT)
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand %s is not an integer type.", 
gsk_sl_type_get_name (ltype));
+      return NULL;
+    }
+  rscalar = gsk_sl_type_get_scalar_type (ltype);
+  if (rscalar != GSK_SL_INT && rscalar != GSK_SL_UINT)
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand %s is not an integer type.", 
gsk_sl_type_get_name (rtype));
+      return NULL;
+    }
+  if (!gsk_sl_type_is_scalar (ltype) && !gsk_sl_type_is_vector (ltype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (ltype));
+      return NULL;
+    }
+  if (!gsk_sl_type_is_scalar (rtype) && !gsk_sl_type_is_vector (rtype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (rtype));
+      return NULL;
+    }
+  if (gsk_sl_type_is_scalar (ltype) && gsk_sl_type_is_vector (rtype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand to shift cannot be a vector if left 
operand is a scalar.");
+      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))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Vector operands do not have the same length.");
+      return NULL;
+    }
+
+  if (gsk_sl_type_is_vector (ltype))
+    return ltype;
+  else if (gsk_sl_type_is_vector (rtype))
+    return gsk_sl_type_get_vector (gsk_sl_type_get_scalar_type (ltype), gsk_sl_type_get_length (rtype));
+  else
+    return ltype;
+}
+
+static GskSlType *
+gsk_sl_relational_check_type (GskSlPreprocessor *preproc,
+                              GskSlType         *ltype,
+                              GskSlType         *rtype)
+{
+  if (!gsk_sl_type_is_scalar (ltype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand to relational operator is not a 
scalar.");
+      return NULL;
+    }
+  if (gsk_sl_type_get_scalar_type (ltype) == GSK_SL_BOOL)
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand to relational operator must not be 
bool.");
+      return NULL;
+    }
+  if (!gsk_sl_type_is_scalar (rtype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand to relational operator is not a 
scalar.");
+      return NULL;
+    }
+  if (gsk_sl_type_get_scalar_type (rtype) == GSK_SL_BOOL)
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand to relational operator must not be 
bool.");
+      return NULL;
+    }
+
+  return gsk_sl_type_get_scalar (GSK_SL_BOOL);
+}
+
+static GskSlType *
+gsk_sl_equal_check_type (GskSlPreprocessor *preproc,
+                         GskSlType         *ltype,
+                         GskSlType         *rtype)
+{
+  if (gsk_sl_type_can_convert (ltype, rtype))
+    return gsk_sl_type_get_scalar (GSK_SL_BOOL);
+  if (gsk_sl_type_can_convert (rtype, ltype))
+    return gsk_sl_type_get_scalar (GSK_SL_BOOL);
+
+  gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Cannot convert %s and %s to the same type for 
comparison.",
+                             gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
+  return NULL;
+}
+
+static GskSlType *
+gsk_sl_logical_check_type (GskSlPreprocessor *preproc,
+                           GskSlType         *ltype,
+                           GskSlType         *rtype)
+{
+  GskSlType *bool_type = gsk_sl_type_get_scalar (GSK_SL_BOOL);
+
+  if (!gsk_sl_type_equal (bool_type, ltype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand of logical operation is not bool, but 
%s",
+                                 gsk_sl_type_get_name (ltype));
+      return NULL;
+    }
+  if (!gsk_sl_type_equal (bool_type, rtype))
+    {
+      gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand of logical operation is not bool, 
but %s",
+                                 gsk_sl_type_get_name (rtype));
+      return NULL;
+    }
+
+  return bool_type;
+}
+
+/* UNIMPLEMENTED */
+
 static GskSlValue *
 gsk_sl_unimplemented_get_constant (GskSlType  *type,
                                    GskSlValue *lvalue,
@@ -765,6 +928,13 @@ gsk_sl_unimplemented_write_spv (GskSpvWriter *writer,
   return 0;
 }
 
+static const GskSlBinary GSK_SL_BINARY_MODULO = {
+  "%",
+  gsk_sl_bitwise_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
 static const GskSlBinary GSK_SL_BINARY_ADDITION = {
   "+",
   gsk_sl_arithmetic_check_type,
@@ -779,6 +949,104 @@ static const GskSlBinary GSK_SL_BINARY_SUBTRACTION = {
   gsk_sl_unimplemented_write_spv
 };
 
+static const GskSlBinary GSK_SL_BINARY_LSHIFT = {
+  "<<",
+  gsk_sl_shift_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_RSHIFT = {
+  ">>",
+  gsk_sl_shift_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_LESS = {
+  "<",
+  gsk_sl_relational_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_GREATER = {
+  ">",
+  gsk_sl_relational_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_LESS_EQUAL = {
+  "<=",
+  gsk_sl_relational_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_GREATER_EQUAL = {
+  ">=",
+  gsk_sl_relational_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_EQUAL = {
+  "==",
+  gsk_sl_equal_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_NOT_EQUAL = {
+  "!=",
+  gsk_sl_equal_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_AND = {
+  "&",
+  gsk_sl_bitwise_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_XOR = {
+  "^",
+  gsk_sl_bitwise_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_OR = {
+  "|",
+  gsk_sl_bitwise_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_LOGICAL_AND = {
+  "&&",
+  gsk_sl_logical_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_LOGICAL_XOR = {
+  "^^",
+  gsk_sl_logical_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
+static const GskSlBinary GSK_SL_BINARY_LOGICAL_OR = {
+  "||",
+  gsk_sl_logical_check_type,
+  gsk_sl_unimplemented_get_constant,
+  gsk_sl_unimplemented_write_spv
+};
+
 /* API */
 
 const char *
@@ -789,11 +1057,11 @@ gsk_sl_binary_get_sign (const GskSlBinary *binary)
 
 GskSlType *
 gsk_sl_binary_check_type (const GskSlBinary *binary,
-                          GskSlPreprocessor *stream,
+                          GskSlPreprocessor *preproc,
                           GskSlType         *ltype,
                           GskSlType         *rtype)
 {
-  return binary->check_type (stream, ltype, rtype);
+  return binary->check_type (preproc, ltype, rtype);
 }
 
 GskSlValue *
@@ -832,7 +1100,7 @@ gsk_sl_binary_get_for_token (GskSlTokenType token)
 
     case GSK_SL_TOKEN_PERCENT:
     case GSK_SL_TOKEN_MOD_ASSIGN:
-      return NULL;
+      return &GSK_SL_BINARY_MODULO;
 
     case GSK_SL_TOKEN_PLUS:
     case GSK_SL_TOKEN_ADD_ASSIGN:
@@ -842,11 +1110,53 @@ gsk_sl_binary_get_for_token (GskSlTokenType token)
     case GSK_SL_TOKEN_SUB_ASSIGN:
       return &GSK_SL_BINARY_SUBTRACTION;
 
+    case GSK_SL_TOKEN_LEFT_OP:
     case GSK_SL_TOKEN_LEFT_ASSIGN:
+      return &GSK_SL_BINARY_LSHIFT;
+
+    case GSK_SL_TOKEN_RIGHT_OP:
     case GSK_SL_TOKEN_RIGHT_ASSIGN:
+      return &GSK_SL_BINARY_RSHIFT;
+
+    case GSK_SL_TOKEN_LEFT_ANGLE:
+      return &GSK_SL_BINARY_LESS;
+
+    case GSK_SL_TOKEN_RIGHT_ANGLE:
+      return &GSK_SL_BINARY_GREATER;
+
+    case GSK_SL_TOKEN_LE_OP:
+      return &GSK_SL_BINARY_LESS_EQUAL;
+
+    case GSK_SL_TOKEN_GE_OP:
+      return &GSK_SL_BINARY_GREATER_EQUAL;
+
+    case GSK_SL_TOKEN_EQ_OP:
+      return &GSK_SL_BINARY_EQUAL;
+
+    case GSK_SL_TOKEN_NE_OP:
+      return &GSK_SL_BINARY_NOT_EQUAL;
+
+    case GSK_SL_TOKEN_AMPERSAND:
     case GSK_SL_TOKEN_AND_ASSIGN:
+      return &GSK_SL_BINARY_AND;
+
+    case GSK_SL_TOKEN_CARET:
     case GSK_SL_TOKEN_XOR_ASSIGN:
+      return &GSK_SL_BINARY_XOR;
+
+    case GSK_SL_TOKEN_VERTICAL_BAR:
     case GSK_SL_TOKEN_OR_ASSIGN:
+      return &GSK_SL_BINARY_OR;
+
+    case GSK_SL_TOKEN_AND_OP:
+      return &GSK_SL_BINARY_LOGICAL_AND;
+
+    case GSK_SL_TOKEN_XOR_OP:
+      return &GSK_SL_BINARY_LOGICAL_XOR;
+
+    case GSK_SL_TOKEN_OR_OP:
+      return &GSK_SL_BINARY_LOGICAL_OR;
+
     default:
       return NULL;
   }
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index f73f78d..8e29c7e 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -263,270 +263,6 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_BINARY = {
   gsk_sl_expression_binary_write_spv
 };
 
-/* OPERATION */
-
-typedef enum {
-  GSK_SL_OPERATION_MOD,
-  GSK_SL_OPERATION_LSHIFT,
-  GSK_SL_OPERATION_RSHIFT,
-  GSK_SL_OPERATION_LESS,
-  GSK_SL_OPERATION_GREATER,
-  GSK_SL_OPERATION_LESS_EQUAL,
-  GSK_SL_OPERATION_GREATER_EQUAL,
-  GSK_SL_OPERATION_EQUAL,
-  GSK_SL_OPERATION_NOT_EQUAL,
-  GSK_SL_OPERATION_AND,
-  GSK_SL_OPERATION_XOR,
-  GSK_SL_OPERATION_OR,
-  GSK_SL_OPERATION_LOGICAL_AND,
-  GSK_SL_OPERATION_LOGICAL_XOR,
-  GSK_SL_OPERATION_LOGICAL_OR
-} GskSlOperation;
-
-typedef struct _GskSlExpressionOperation GskSlExpressionOperation;
-
-struct _GskSlExpressionOperation {
-  GskSlExpression parent;
-
-  GskSlOperation op;
-  GskSlExpression *left;
-  GskSlExpression *right;
-};
-
-static void
-gsk_sl_expression_operation_free (GskSlExpression *expression)
-{
-  GskSlExpressionOperation *operation = (GskSlExpressionOperation *) expression;
-
-  gsk_sl_expression_unref (operation->left);
-  if (operation->right)
-    gsk_sl_expression_unref (operation->right);
-
-  g_slice_free (GskSlExpressionOperation, operation);
-}
-
-static void
-gsk_sl_expression_operation_print (const GskSlExpression *expression,
-                                   GskSlPrinter          *printer)
-{
-  const char *op_str[] = {
-    [GSK_SL_OPERATION_MOD] = " % ",
-    [GSK_SL_OPERATION_LSHIFT] = " << ",
-    [GSK_SL_OPERATION_RSHIFT] = " >> ",
-    [GSK_SL_OPERATION_LESS] = " < ",
-    [GSK_SL_OPERATION_GREATER] = " > ",
-    [GSK_SL_OPERATION_LESS_EQUAL] = " <= ",
-    [GSK_SL_OPERATION_GREATER_EQUAL] = " >= ",
-    [GSK_SL_OPERATION_EQUAL] = " == ",
-    [GSK_SL_OPERATION_NOT_EQUAL] = " != ",
-    [GSK_SL_OPERATION_AND] = " & ",
-    [GSK_SL_OPERATION_XOR] = " ^ ",
-    [GSK_SL_OPERATION_OR] = " | ",
-    [GSK_SL_OPERATION_LOGICAL_AND] = " && ",
-    [GSK_SL_OPERATION_LOGICAL_XOR] = " ^^ ",
-    [GSK_SL_OPERATION_LOGICAL_OR] = " || "
-  };
-  GskSlExpressionOperation *operation = (GskSlExpressionOperation *) expression;
-
-  /* XXX: figure out the need for bracketing here */
-
-  gsk_sl_expression_print (operation->left, printer);
-  gsk_sl_printer_append (printer, op_str[operation->op]);
-  gsk_sl_expression_print (operation->right, printer);
-}
-
-static GskSlType *
-gsk_sl_expression_bitwise_type_check (GskSlPreprocessor *stream,
-                                      GskSlType         *ltype,
-                                      GskSlType         *rtype)
-{
-  GskSlScalarType lscalar, rscalar;
-
-  lscalar = gsk_sl_type_get_scalar_type (ltype);
-  if (lscalar != GSK_SL_INT && lscalar != GSK_SL_UINT)
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Left operand %s is not an integer type.", 
gsk_sl_type_get_name (ltype));
-      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, TYPE_MISMATCH, "Right operand %s is not an integer type.", 
gsk_sl_type_get_name (rtype));
-      return NULL;
-    }
-  if (!gsk_sl_type_is_scalar (ltype) && !gsk_sl_type_is_vector (ltype))
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Left operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (ltype));
-      return NULL;
-    }
-  if (!gsk_sl_type_is_scalar (rtype) && !gsk_sl_type_is_vector (rtype))
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Right operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (rtype));
-      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, TYPE_MISMATCH,
-                                   "Vector operands %s and %s do not have the same length.",
-                                   gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
-      return NULL;
-    }
-
-  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 gsk_sl_type_get_vector (rscalar, gsk_sl_type_get_length (ltype));
-}
-
-static gboolean
-gsk_sl_expression_shift_type_check (GskSlPreprocessor *stream,
-                                    GskSlType         *ltype,
-                                    GskSlType         *rtype)
-{
-  GskSlScalarType lscalar, rscalar;
-
-  lscalar = gsk_sl_type_get_scalar_type (ltype);
-  if (lscalar != GSK_SL_INT && lscalar != GSK_SL_UINT)
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Left operand %s is not an integer type.", 
gsk_sl_type_get_name (ltype));
-      return FALSE;
-    }
-  rscalar = gsk_sl_type_get_scalar_type (ltype);
-  if (rscalar != GSK_SL_INT && rscalar != GSK_SL_UINT)
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Right operand %s is not an integer type.", 
gsk_sl_type_get_name (rtype));
-      return FALSE;
-    }
-  if (!gsk_sl_type_is_scalar (ltype) && !gsk_sl_type_is_vector (ltype))
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Left operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (ltype));
-      return FALSE;
-    }
-  if (!gsk_sl_type_is_scalar (rtype) && !gsk_sl_type_is_vector (rtype))
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Right operand %s is neither a scalar nor a 
vector.", gsk_sl_type_get_name (rtype));
-      return FALSE;
-    }
-  if (gsk_sl_type_is_scalar (ltype) && gsk_sl_type_is_vector (rtype))
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Right operand to shift cannot be a vector if left 
operand is a scalar.");
-      return FALSE;
-    }
-  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, TYPE_MISMATCH, "Vector operands do not have the same length.");
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-static gboolean
-gsk_sl_expression_relational_type_check (GskSlPreprocessor *stream,
-                                         GskSlType        *ltype,
-                                         GskSlType        *rtype)
-{
-  if (!gsk_sl_type_is_scalar (ltype))
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Left operand to relational operator is not a 
scalar.");
-      return FALSE;
-    }
-  if (gsk_sl_type_get_scalar_type (ltype) == GSK_SL_BOOL)
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Left operand to relational operator must not be 
bool.");
-      return FALSE;
-    }
-  if (!gsk_sl_type_is_scalar (rtype))
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Right operand to relational operator is not a 
scalar.");
-      return FALSE;
-    }
-  if (gsk_sl_type_get_scalar_type (rtype) == GSK_SL_BOOL)
-    {
-      if (stream)
-        gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Right operand to relational operator must not be 
bool.");
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-static GskSlType *
-gsk_sl_expression_operation_get_return_type (const GskSlExpression *expression)
-{
-  GskSlExpressionOperation *operation = (GskSlExpressionOperation *) expression;
-
-  switch (operation->op)
-  {
-    case GSK_SL_OPERATION_LSHIFT:
-    case GSK_SL_OPERATION_RSHIFT:
-      return gsk_sl_expression_get_return_type (operation->left);
-    case GSK_SL_OPERATION_MOD:
-    case GSK_SL_OPERATION_AND:
-    case GSK_SL_OPERATION_XOR:
-    case GSK_SL_OPERATION_OR:
-      return gsk_sl_expression_bitwise_type_check (NULL,
-                                                   gsk_sl_expression_get_return_type (operation->left),
-                                                   gsk_sl_expression_get_return_type (operation->right));
-    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:
-    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 GskSlValue *
-gsk_sl_expression_operation_get_constant (const GskSlExpression *expression)
-{
-  //const GskSlExpressionOperation *operation = (const GskSlExpressionOperation *) expression;
-
-  /* FIXME: These need constant evaluations */
-  return NULL;
-}
-
-static guint32
-gsk_sl_expression_operation_write_spv (const GskSlExpression *expression,
-                                       GskSpvWriter          *writer)
-{
-  g_assert_not_reached ();
-
-  return 0;
-}
-
-static const GskSlExpressionClass GSK_SL_EXPRESSION_OPERATION = {
-  gsk_sl_expression_operation_free,
-  gsk_sl_expression_operation_print,
-  gsk_sl_expression_operation_get_return_type,
-  gsk_sl_expression_operation_get_constant,
-  gsk_sl_expression_operation_write_spv
-};
-
 /* REFERENCE */
 
 typedef struct _GskSlExpressionReference GskSlExpressionReference;
@@ -2111,67 +1847,42 @@ gsk_sl_expression_parse_multiplicative (GskSlScope        *scope,
                                         GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
+  const GskSlBinary *binary;
   GskSlExpression *expression, *right;
-  enum { MUL, DIV, MOD } op;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_unary (scope, stream);
 
   while (TRUE)
     {
       token = gsk_sl_preprocessor_get (stream);
-      if (gsk_sl_token_is (token, GSK_SL_TOKEN_STAR))
-        op = MUL;
-      else if (gsk_sl_token_is (token, GSK_SL_TOKEN_SLASH))
-        op = DIV;
-      else if (gsk_sl_token_is (token, GSK_SL_TOKEN_PERCENT))
-        op = MOD;
-      else
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_STAR) &&
+          !gsk_sl_token_is (token, GSK_SL_TOKEN_SLASH) &&
+          !gsk_sl_token_is (token, GSK_SL_TOKEN_PERCENT))
         return expression;
 
+      binary = gsk_sl_binary_get_for_token (token->type);
       gsk_sl_preprocessor_consume (stream, NULL);
+
       right = gsk_sl_expression_parse_unary (scope, stream);
-      if (op == MUL || op == DIV)
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          const GskSlBinary *binary;
-          GskSlType *result_type;
-
-          binary = gsk_sl_binary_get_for_token (op == MUL ? GSK_SL_TOKEN_STAR : GSK_SL_TOKEN_SLASH);
-          result_type = gsk_sl_binary_check_type (binary,
-                                                  stream,
-                                                  gsk_sl_expression_get_return_type (expression),
-                                                  gsk_sl_expression_get_return_type (right));
-          if (result_type)
-            {
-              GskSlExpressionBinary *binary_expr;
-              binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
-              binary_expr->binary = binary;
-              binary_expr->type = gsk_sl_type_ref (result_type);
-              binary_expr->left = expression;
-              binary_expr->right = right;
-              expression = (GskSlExpression *) binary_expr;
-            }
-          else
-            {
-              gsk_sl_expression_unref ((GskSlExpression *) right);
-            }
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          if (gsk_sl_expression_bitwise_type_check (stream,
-                                                    gsk_sl_expression_get_return_type (expression),
-                                                    gsk_sl_expression_get_return_type (right)))
-            {
-              GskSlExpressionOperation *operation;
-              operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-              operation->op = GSK_SL_OPERATION_MOD;
-              operation->left = expression;
-              operation->right = right;
-              expression = (GskSlExpression *) operation;
-            }
-          else
-            {
-              gsk_sl_expression_unref ((GskSlExpression *) right);
-            }
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2229,37 +1940,41 @@ gsk_sl_expression_parse_shift (GskSlScope        *scope,
                                GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
-  GskSlOperation op;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_additive (scope, stream);
 
   while (TRUE)
     {
       token = gsk_sl_preprocessor_get (stream);
-      if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_OP))
-        op = GSK_SL_OPERATION_LSHIFT;
-      else if (gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_OP))
-        op = GSK_SL_OPERATION_RSHIFT;
-      else
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_OP) &&
+          !gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_OP))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = op;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_additive (scope, stream);
-      if (!gsk_sl_expression_shift_type_check (stream,
-                                               gsk_sl_expression_get_return_type (operation->left),
-                                               gsk_sl_expression_get_return_type (operation->right)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_additive (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2271,41 +1986,43 @@ gsk_sl_expression_parse_relational (GskSlScope        *scope,
                                     GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
-  GskSlOperation op;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_shift (scope, stream);
 
   while (TRUE)
     {
       token = gsk_sl_preprocessor_get (stream);
-      if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_ANGLE))
-        op = GSK_SL_OPERATION_LESS;
-      else if (gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_ANGLE))
-        op = GSK_SL_OPERATION_GREATER;
-      else if (gsk_sl_token_is (token, GSK_SL_TOKEN_LE_OP))
-        op = GSK_SL_OPERATION_LESS_EQUAL;
-      else if (gsk_sl_token_is (token, GSK_SL_TOKEN_GE_OP))
-        op = GSK_SL_OPERATION_GREATER_EQUAL;
-      else
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_ANGLE) &&
+          !gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_ANGLE) &&
+          !gsk_sl_token_is (token, GSK_SL_TOKEN_LE_OP) &&
+          !gsk_sl_token_is (token, GSK_SL_TOKEN_GE_OP))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = op;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_shift (scope, stream);
-      if (!gsk_sl_expression_relational_type_check (stream,
-                                                    gsk_sl_expression_get_return_type (operation->left),
-                                                    gsk_sl_expression_get_return_type (operation->right)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_shift (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2317,28 +2034,42 @@ gsk_sl_expression_parse_equality (GskSlScope        *scope,
                                   GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
-  GskSlOperation op;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_relational (scope, stream);
 
   while (TRUE)
     {
       token = gsk_sl_preprocessor_get (stream);
-      if (gsk_sl_token_is (token, GSK_SL_TOKEN_EQ_OP))
-        op = GSK_SL_OPERATION_EQUAL;
-      else if (gsk_sl_token_is (token, GSK_SL_TOKEN_NE_OP))
-        op = GSK_SL_OPERATION_NOT_EQUAL;
-      else
+      if (!gsk_sl_token_is (token, GSK_SL_TOKEN_EQ_OP) &&
+          !gsk_sl_token_is (token, GSK_SL_TOKEN_NE_OP))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = op;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_relational (scope, stream);
-      expression = (GskSlExpression *) operation;
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_relational (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
+        {
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
+        }
+      else
+        {
+          gsk_sl_expression_unref ((GskSlExpression *) right);
+        }
     }
 
   return expression;
@@ -2349,8 +2080,9 @@ gsk_sl_expression_parse_and (GskSlScope        *scope,
                              GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_equality (scope, stream);
 
@@ -2360,21 +2092,28 @@ gsk_sl_expression_parse_and (GskSlScope        *scope,
       if (!gsk_sl_token_is (token, GSK_SL_TOKEN_AMPERSAND))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = GSK_SL_OPERATION_AND;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_equality (scope, stream);
-      if (!gsk_sl_expression_bitwise_type_check (stream,
-                                                 gsk_sl_expression_get_return_type (operation->left),
-                                                 gsk_sl_expression_get_return_type (operation->right)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_equality (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2386,8 +2125,9 @@ gsk_sl_expression_parse_xor (GskSlScope        *scope,
                              GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_and (scope, stream);
 
@@ -2397,21 +2137,28 @@ gsk_sl_expression_parse_xor (GskSlScope        *scope,
       if (!gsk_sl_token_is (token, GSK_SL_TOKEN_CARET))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = GSK_SL_OPERATION_XOR;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_and (scope, stream);
-      if (!gsk_sl_expression_bitwise_type_check (stream,
-                                                 gsk_sl_expression_get_return_type (operation->left),
-                                                 gsk_sl_expression_get_return_type (operation->right)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_and (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2423,8 +2170,9 @@ gsk_sl_expression_parse_or (GskSlScope        *scope,
                             GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_xor (scope, stream);
 
@@ -2434,21 +2182,28 @@ gsk_sl_expression_parse_or (GskSlScope        *scope,
       if (!gsk_sl_token_is (token, GSK_SL_TOKEN_VERTICAL_BAR))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = GSK_SL_OPERATION_OR;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_xor (scope, stream);
-      if (!gsk_sl_expression_bitwise_type_check (stream,
-                                                 gsk_sl_expression_get_return_type (operation->left),
-                                                 gsk_sl_expression_get_return_type (operation->right)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_xor (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2460,8 +2215,9 @@ gsk_sl_expression_parse_logical_and (GskSlScope        *scope,
                                      GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_or (scope, stream);
 
@@ -2471,33 +2227,28 @@ gsk_sl_expression_parse_logical_and (GskSlScope        *scope,
       if (!gsk_sl_token_is (token, GSK_SL_TOKEN_AND_OP))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = GSK_SL_OPERATION_LOGICAL_AND;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_or (scope, stream);
-      if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
-                                    gsk_sl_expression_get_return_type (operation->right)))
-        {
-          gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
-                                     "Right operand of && expression is not bool but %s",
-                                     gsk_sl_type_get_name (gsk_sl_expression_get_return_type 
(operation->right)));
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
-        }
-      else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
-                                         gsk_sl_expression_get_return_type (expression)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_or (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
-                                     "Left operand of && expression is not bool but %s",
-                                     gsk_sl_type_get_name (gsk_sl_expression_get_return_type (expression)));
-          expression = operation->right;
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2509,8 +2260,9 @@ gsk_sl_expression_parse_logical_xor (GskSlScope        *scope,
                                      GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_logical_and (scope, stream);
 
@@ -2520,33 +2272,28 @@ gsk_sl_expression_parse_logical_xor (GskSlScope        *scope,
       if (!gsk_sl_token_is (token, GSK_SL_TOKEN_XOR_OP))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = GSK_SL_OPERATION_LOGICAL_XOR;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_logical_and (scope, stream);
-      if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
-                                    gsk_sl_expression_get_return_type (operation->right)))
-        {
-          gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
-                                     "Right operand of ^^ expression is not bool but %s",
-                                     gsk_sl_type_get_name (gsk_sl_expression_get_return_type 
(operation->right)));
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
-        }
-      else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
-                                         gsk_sl_expression_get_return_type (expression)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_logical_and (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
-                                     "Left operand of ^^ expression is not bool but %s",
-                                     gsk_sl_type_get_name (gsk_sl_expression_get_return_type (expression)));
-          expression = operation->right;
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 
@@ -2558,8 +2305,9 @@ gsk_sl_expression_parse_logical_or (GskSlScope        *scope,
                                     GskSlPreprocessor *stream)
 {
   const GskSlToken *token;
-  GskSlExpression *expression;
-  GskSlExpressionOperation *operation;
+  const GskSlBinary *binary;
+  GskSlExpression *expression, *right;
+  GskSlType *result_type;
 
   expression = gsk_sl_expression_parse_logical_xor (scope, stream);
 
@@ -2569,33 +2317,28 @@ gsk_sl_expression_parse_logical_or (GskSlScope        *scope,
       if (!gsk_sl_token_is (token, GSK_SL_TOKEN_OR_OP))
         return expression;
 
-      operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
-      operation->left = expression;
-      operation->op = GSK_SL_OPERATION_LOGICAL_OR;
-      gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
-      operation->right = gsk_sl_expression_parse_logical_xor (scope, stream);
-      if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
-                                    gsk_sl_expression_get_return_type (operation->right)))
-        {
-          gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
-                                     "Right operand of || expression is not bool but %s",
-                                     gsk_sl_type_get_name (gsk_sl_expression_get_return_type 
(operation->right)));
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
-        }
-      else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
-                                         gsk_sl_expression_get_return_type (expression)))
+      binary = gsk_sl_binary_get_for_token (token->type);
+      gsk_sl_preprocessor_consume (stream, NULL);
+
+      right = gsk_sl_expression_parse_logical_xor (scope, stream);
+
+      result_type = gsk_sl_binary_check_type (binary,
+                                              stream,
+                                              gsk_sl_expression_get_return_type (expression),
+                                              gsk_sl_expression_get_return_type (right));
+      if (result_type)
         {
-          gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
-                                     "Left operand of || expression is not bool but %s",
-                                     gsk_sl_type_get_name (gsk_sl_expression_get_return_type (expression)));
-          expression = operation->right;
-          gsk_sl_expression_ref (expression);
-          gsk_sl_expression_unref ((GskSlExpression *) operation);
+          GskSlExpressionBinary *binary_expr;
+          binary_expr = gsk_sl_expression_new (GskSlExpressionBinary, &GSK_SL_EXPRESSION_BINARY);
+          binary_expr->binary = binary;
+          binary_expr->type = gsk_sl_type_ref (result_type);
+          binary_expr->left = expression;
+          binary_expr->right = right;
+          expression = (GskSlExpression *) binary_expr;
         }
       else
         {
-          expression = (GskSlExpression *) operation;
+          gsk_sl_expression_unref ((GskSlExpression *) right);
         }
     }
 


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