[gtk+/wip/otte/shader: 72/226] gsksl: Split Expression from Node
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 72/226] gsksl: Split Expression from Node
- Date: Mon, 30 Oct 2017 02:06:35 +0000 (UTC)
commit 7e8604372db3592570584b8a01012e214bf6c7c3
Author: Benjamin Otte <otte redhat com>
Date: Sun Sep 24 19:53:17 2017 +0200
gsksl: Split Expression from Node
gsk/gskslexpression.c | 1823 +++++++++++++++++++++++++++++++++++++++
gsk/gskslexpressionprivate.h | 47 +
gsk/gskslnode.c | 1862 ++--------------------------------------
gsk/gskslnodeprivate.h | 4 -
gsk/gskslpreprocessor.c | 2 +-
gsk/gskslpreprocessorprivate.h | 2 +-
gsk/gskslprogram.c | 2 +-
gsk/gsksltypesprivate.h | 1 +
gsk/meson.build | 1 +
9 files changed, 1949 insertions(+), 1795 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
new file mode 100644
index 0000000..aafd3e3
--- /dev/null
+++ b/gsk/gskslexpression.c
@@ -0,0 +1,1823 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gskslexpressionprivate.h"
+
+#include "gskslpreprocessorprivate.h"
+#include "gskslfunctionprivate.h"
+#include "gskslnodeprivate.h"
+#include "gskslpointertypeprivate.h"
+#include "gskslscopeprivate.h"
+#include "gsksltokenizerprivate.h"
+#include "gsksltypeprivate.h"
+#include "gskslvariableprivate.h"
+#include "gskspvwriterprivate.h"
+
+#include <string.h>
+
+typedef struct _GskSlExpressionClass GskSlExpressionClass;
+
+struct _GskSlExpression {
+ const GskSlExpressionClass *class;
+ guint ref_count;
+};
+
+struct _GskSlExpressionClass {
+ void (* free) (GskSlExpression *expression);
+
+ void (* print) (const GskSlExpression *expression,
+ GString *string);
+ GskSlType * (* get_return_type) (const GskSlExpression *expression);
+ gboolean (* is_constant) (const GskSlExpression *expression);
+ guint32 (* write_spv) (const GskSlExpression *expression,
+ GskSpvWriter *writer);
+};
+
+static GskSlExpression *
+gsk_sl_expression_alloc (const GskSlExpressionClass *klass,
+ gsize size)
+{
+ GskSlExpression *expression;
+
+ expression = g_slice_alloc0 (size);
+
+ expression->class = klass;
+ expression->ref_count = 1;
+
+ return expression;
+}
+#define gsk_sl_expression_new(_name, _klass) ((_name *) gsk_sl_expression_alloc ((_klass), sizeof (_name)))
+
+/* ASSIGNMENT */
+
+typedef struct _GskSlExpressionAssignment GskSlExpressionAssignment;
+
+struct _GskSlExpressionAssignment {
+ GskSlExpression parent;
+
+ GskSlTokenType op;
+ GskSlExpression *lvalue;
+ GskSlExpression *rvalue;
+};
+
+static void
+gsk_sl_expression_assignment_free (GskSlExpression *expression)
+{
+ GskSlExpressionAssignment *assignment = (GskSlExpressionAssignment *) expression;
+
+ gsk_sl_expression_unref (assignment->lvalue);
+ if (assignment->rvalue)
+ gsk_sl_expression_unref (assignment->rvalue);
+
+ g_slice_free (GskSlExpressionAssignment, assignment);
+}
+
+static void
+gsk_sl_expression_assignment_print (const GskSlExpression *expression,
+ GString *string)
+{
+ const GskSlExpressionAssignment *assignment = (const GskSlExpressionAssignment *) expression;
+
+ gsk_sl_expression_print (assignment->lvalue, string);
+
+ switch ((guint) assignment->op)
+ {
+ case GSK_SL_TOKEN_EQUAL:
+ g_string_append (string, " = ");
+ break;
+ case GSK_SL_TOKEN_MUL_ASSIGN:
+ g_string_append (string, " *= ");
+ break;
+ case GSK_SL_TOKEN_DIV_ASSIGN:
+ g_string_append (string, " /= ");
+ break;
+ case GSK_SL_TOKEN_MOD_ASSIGN:
+ g_string_append (string, " %= ");
+ break;
+ case GSK_SL_TOKEN_ADD_ASSIGN:
+ g_string_append (string, " += ");
+ break;
+ case GSK_SL_TOKEN_SUB_ASSIGN:
+ g_string_append (string, " -= ");
+ break;
+ case GSK_SL_TOKEN_LEFT_ASSIGN:
+ g_string_append (string, " <<= ");
+ break;
+ case GSK_SL_TOKEN_RIGHT_ASSIGN:
+ g_string_append (string, " >>= ");
+ break;
+ case GSK_SL_TOKEN_AND_ASSIGN:
+ g_string_append (string, " &= ");
+ break;
+ case GSK_SL_TOKEN_XOR_ASSIGN:
+ g_string_append (string, " ^= ");
+ break;
+ case GSK_SL_TOKEN_OR_ASSIGN:
+ g_string_append (string, " |= ");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ gsk_sl_expression_print (assignment->rvalue, string);
+}
+
+static GskSlType *
+gsk_sl_expression_assignment_get_return_type (const GskSlExpression *expression)
+{
+ const GskSlExpressionAssignment *assignment = (const GskSlExpressionAssignment *) expression;
+
+ return gsk_sl_expression_get_return_type (assignment->lvalue);
+}
+
+static gboolean
+gsk_sl_expression_assignment_is_constant (const GskSlExpression *expression)
+{
+ return FALSE;
+}
+
+static guint32
+gsk_sl_expression_assignment_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ g_assert_not_reached ();
+
+ return 0;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_ASSIGNMENT = {
+ gsk_sl_expression_assignment_free,
+ gsk_sl_expression_assignment_print,
+ gsk_sl_expression_assignment_get_return_type,
+ gsk_sl_expression_assignment_is_constant,
+ gsk_sl_expression_assignment_write_spv
+};
+
+/* BINARY */
+
+typedef enum {
+ GSK_SL_OPERATION_MUL,
+ GSK_SL_OPERATION_DIV,
+ GSK_SL_OPERATION_MOD,
+ GSK_SL_OPERATION_ADD,
+ GSK_SL_OPERATION_SUB,
+ 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,
+ GString *string)
+{
+ const char *op_str[] = {
+ [GSK_SL_OPERATION_MUL] = " * ",
+ [GSK_SL_OPERATION_DIV] = " / ",
+ [GSK_SL_OPERATION_MOD] = " % ",
+ [GSK_SL_OPERATION_ADD] = " + ",
+ [GSK_SL_OPERATION_SUB] = " - ",
+ [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, string);
+ g_string_append (string, op_str[operation->op]);
+ gsk_sl_expression_print (operation->right, string);
+}
+
+static GskSlType *
+gsk_sl_expression_arithmetic_type_check (GskSlPreprocessor *stream,
+ gboolean multiply,
+ GskSlType *ltype,
+ GskSlType *rtype)
+{
+ GskSlScalarType scalar;
+
+ if (gsk_sl_scalar_type_can_convert (gsk_sl_type_get_scalar_type (ltype),
+ gsk_sl_type_get_scalar_type (rtype)))
+ scalar = gsk_sl_type_get_scalar_type (ltype);
+ else if (gsk_sl_scalar_type_can_convert (gsk_sl_type_get_scalar_type (rtype),
+ gsk_sl_type_get_scalar_type (ltype)))
+ scalar = gsk_sl_type_get_scalar_type (rtype);
+ else
+ {
+ if (stream)
+ {
+ gsk_sl_preprocessor_error (stream, "Operand types %s and %s do not share compatible scalar types.",
+ gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
+ }
+ return NULL;
+ }
+
+ if (gsk_sl_type_is_matrix (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ if (multiply)
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (gsk_sl_type_get_index_type
(rtype)))
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Matrices to multiplication have incompatible
dimensions.");
+ return NULL;
+ }
+ return gsk_sl_type_get_matrix (scalar,
+ gsk_sl_type_get_length (gsk_sl_type_get_index_type (ltype)),
+ gsk_sl_type_get_length (rtype));
+ }
+ else
+ {
+ if (gsk_sl_type_can_convert (ltype, rtype))
+ {
+ return ltype;
+ }
+ else if (gsk_sl_type_can_convert (rtype, ltype))
+ {
+ return rtype;
+ }
+ else
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Matrix types %s and %s have different size.",
+ gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
+ return NULL;
+ }
+ }
+ }
+ else if (gsk_sl_type_is_vector (rtype))
+ {
+ if (multiply)
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Matrix column count doesn't match vector length.");
+ return NULL;
+ }
+ return gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length (gsk_sl_type_get_index_type
(ltype)));
+ }
+ else
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Cannot perform arithmetic operation between matrix and
vector.");
+ return NULL;
+ }
+ }
+ else if (gsk_sl_type_is_scalar (rtype))
+ {
+ return gsk_sl_type_get_matrix (scalar,
+ gsk_sl_type_get_length (ltype),
+ gsk_sl_type_get_length (gsk_sl_type_get_index_type (ltype)));
+ }
+ else
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Right operand is incompatible type for arithemtic
operation.");
+ return NULL;
+ }
+ }
+ else if (gsk_sl_type_is_vector (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ if (multiply)
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (gsk_sl_type_get_index_type
(rtype)))
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Vector length for %s doesn't match row count for %s",
+ gsk_sl_type_get_name (ltype), gsk_sl_type_get_name
(rtype));
+ return NULL;
+ }
+ return gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length (rtype));
+ }
+ else
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Cannot perform arithmetic operation between vector and
matrix.");
+ return NULL;
+ }
+ }
+ else if (gsk_sl_type_is_vector (rtype))
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Vector operands %s and %s to arithmetic operation have
different length.",
+ gsk_sl_type_get_name (ltype), gsk_sl_type_get_name
(rtype));
+ return NULL;
+ }
+ return gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length (ltype));
+ }
+ else if (gsk_sl_type_is_scalar (rtype))
+ {
+ return gsk_sl_type_get_vector (scalar,
+ gsk_sl_type_get_length (ltype));
+ }
+ else
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Right operand is incompatible type for arithemtic
operation.");
+ return NULL;
+ }
+ }
+ else if (gsk_sl_type_is_scalar (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ return gsk_sl_type_get_matrix (scalar,
+ gsk_sl_type_get_length (rtype),
+ gsk_sl_type_get_length (gsk_sl_type_get_index_type (rtype)));
+ }
+ else if (gsk_sl_type_is_vector (rtype))
+ {
+ return gsk_sl_type_get_vector (scalar,
+ gsk_sl_type_get_length (rtype));
+ }
+ else if (gsk_sl_type_is_scalar (rtype))
+ {
+ return gsk_sl_type_get_scalar (scalar);
+ }
+ else
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Right operand is incompatible type for arithemtic
operation.");
+ return NULL;
+ }
+ }
+ else
+ {
+ if (stream)
+ gsk_sl_preprocessor_error (stream, "Left operand is incompatible type for arithemtic operation.");
+ return NULL;
+ }
+}
+
+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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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_MUL:
+ return gsk_sl_expression_arithmetic_type_check (NULL,
+ TRUE,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right));
+ case GSK_SL_OPERATION_DIV:
+ case GSK_SL_OPERATION_ADD:
+ case GSK_SL_OPERATION_SUB:
+ return gsk_sl_expression_arithmetic_type_check (NULL,
+ FALSE,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right));
+ 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 gboolean
+gsk_sl_expression_operation_is_constant (const GskSlExpression *expression)
+{
+ const GskSlExpressionOperation *operation = (const GskSlExpressionOperation *) expression;
+
+ return gsk_sl_expression_is_constant (operation->left)
+ && gsk_sl_expression_is_constant (operation->right);
+}
+
+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_is_constant,
+ gsk_sl_expression_operation_write_spv
+};
+
+/* REFERENCE */
+
+typedef struct _GskSlExpressionReference GskSlExpressionReference;
+
+struct _GskSlExpressionReference {
+ GskSlExpression parent;
+
+ GskSlVariable *variable;
+};
+
+static void
+gsk_sl_expression_reference_free (GskSlExpression *expression)
+{
+ GskSlExpressionReference *reference = (GskSlExpressionReference *) expression;
+
+ gsk_sl_variable_unref (reference->variable);
+
+ g_slice_free (GskSlExpressionReference, reference);
+}
+
+static void
+gsk_sl_expression_reference_print (const GskSlExpression *expression,
+ GString *string)
+{
+ const GskSlExpressionReference *reference = (const GskSlExpressionReference *) expression;
+
+ g_string_append (string, gsk_sl_variable_get_name (reference->variable));
+}
+
+static GskSlType *
+gsk_sl_expression_reference_get_return_type (const GskSlExpression *expression)
+{
+ const GskSlExpressionReference *reference = (const GskSlExpressionReference *) expression;
+
+ return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (reference->variable));
+}
+
+static gboolean
+gsk_sl_expression_reference_is_constant (const GskSlExpression *expression)
+{
+ return FALSE;
+}
+
+static guint32
+gsk_sl_expression_reference_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ GskSlExpressionReference *reference = (GskSlExpressionReference *) expression;
+ guint32 declaration_id, result_id, type_id;
+
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type
(reference->variable)));
+ declaration_id = gsk_spv_writer_get_id_for_variable (writer, reference->variable);
+ result_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 4, GSK_SPV_OP_LOAD,
+ (guint32[3]) { type_id,
+ result_id,
+ declaration_id });
+
+ return result_id;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_REFERENCE = {
+ gsk_sl_expression_reference_free,
+ gsk_sl_expression_reference_print,
+ gsk_sl_expression_reference_get_return_type,
+ gsk_sl_expression_reference_is_constant,
+ gsk_sl_expression_reference_write_spv
+};
+
+/* FUNCTION_CALL */
+
+typedef struct _GskSlExpressionFunctionCall GskSlExpressionFunctionCall;
+
+struct _GskSlExpressionFunctionCall {
+ GskSlExpression parent;
+
+ GskSlFunction *function;
+ GskSlExpression **arguments;
+ guint n_arguments;
+};
+
+static void
+gsk_sl_expression_function_call_free (GskSlExpression *expression)
+{
+ GskSlExpressionFunctionCall *function_call = (GskSlExpressionFunctionCall *) expression;
+ guint i;
+
+ for (i = 0; i < function_call->n_arguments; i++)
+ {
+ gsk_sl_expression_unref (function_call->arguments[i]);
+ }
+ g_free (function_call->arguments);
+
+ gsk_sl_function_unref (function_call->function);
+
+ g_slice_free (GskSlExpressionFunctionCall, function_call);
+}
+
+static void
+gsk_sl_expression_function_call_print (const GskSlExpression *expression,
+ GString *string)
+{
+ const GskSlExpressionFunctionCall *function_call = (const GskSlExpressionFunctionCall *) expression;
+ guint i;
+
+ gsk_sl_function_print_name (function_call->function, string);
+ g_string_append (string, " (");
+
+ for (i = 0; i < function_call->n_arguments; i++)
+ {
+ if (i > 0)
+ g_string_append (string, ", ");
+ gsk_sl_expression_print (function_call->arguments[i], string);
+ }
+
+ g_string_append (string, ")");
+}
+
+static GskSlType *
+gsk_sl_expression_function_call_get_return_type (const GskSlExpression *expression)
+{
+ const GskSlExpressionFunctionCall *function_call = (const GskSlExpressionFunctionCall *) expression;
+
+ return gsk_sl_function_get_return_type (function_call->function);
+}
+
+static gboolean
+gsk_sl_expression_function_call_is_constant (const GskSlExpression *expression)
+{
+ return FALSE;
+}
+
+static guint32
+gsk_sl_expression_function_call_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ g_assert_not_reached ();
+
+ return 0;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = {
+ gsk_sl_expression_function_call_free,
+ gsk_sl_expression_function_call_print,
+ gsk_sl_expression_function_call_get_return_type,
+ gsk_sl_expression_function_call_is_constant,
+ gsk_sl_expression_function_call_write_spv
+};
+
+/* CONSTANT */
+
+typedef struct _GskSlExpressionConstant GskSlExpressionConstant;
+
+struct _GskSlExpressionConstant {
+ GskSlExpression parent;
+
+ GskSlScalarType type;
+ union {
+ gint32 i32;
+ guint32 u32;
+ float f;
+ double d;
+ gboolean b;
+ };
+};
+
+static void
+gsk_sl_expression_constant_free (GskSlExpression *expression)
+{
+ GskSlExpressionConstant *constant = (GskSlExpressionConstant *) expression;
+
+ g_slice_free (GskSlExpressionConstant, constant);
+}
+
+static void
+gsk_sl_expression_constant_print (const GskSlExpression *expression,
+ GString *string)
+{
+ const GskSlExpressionConstant *constant = (const GskSlExpressionConstant *) expression;
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+ switch (constant->type)
+ {
+ case GSK_SL_FLOAT:
+ g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, constant->f);
+ g_string_append (string, buf);
+ if (strchr (buf, '.') == NULL)
+ g_string_append (string, ".0");
+ break;
+
+ case GSK_SL_DOUBLE:
+ g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, constant->d);
+ g_string_append (string, buf);
+ if (strchr (buf, '.') == NULL)
+ g_string_append (string, ".0");
+ g_string_append (string, "lf");
+ break;
+
+ case GSK_SL_INT:
+ g_string_append_printf (string, "%i", (gint) constant->i32);
+ break;
+
+ case GSK_SL_UINT:
+ g_string_append_printf (string, "%uu", (guint) constant->u32);
+ break;
+
+ case GSK_SL_BOOL:
+ g_string_append (string, constant->b ? "true" : "false");
+ break;
+
+ case GSK_SL_VOID:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static GskSlType *
+gsk_sl_expression_constant_get_return_type (const GskSlExpression *expression)
+{
+ const GskSlExpressionConstant *constant = (const GskSlExpressionConstant *) expression;
+
+ return gsk_sl_type_get_scalar (constant->type);
+}
+
+static gboolean
+gsk_sl_expression_constant_is_constant (const GskSlExpression *expression)
+{
+ return TRUE;
+}
+
+static guint32
+gsk_sl_expression_constant_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ const GskSlExpressionConstant *constant = (const GskSlExpressionConstant *) expression;
+ guint32 type_id, result_id;
+
+ switch (constant->type)
+ {
+ case GSK_SL_FLOAT:
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_FLOAT));
+ result_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_DECLARE,
+ 4, GSK_SPV_OP_CONSTANT,
+ (guint32[3]) { type_id,
+ result_id,
+ *(guint32 *) &constant->f });
+ break;
+
+ case GSK_SL_DOUBLE:
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_DOUBLE));
+ result_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_DECLARE,
+ 5, GSK_SPV_OP_CONSTANT,
+ (guint32[4]) { type_id,
+ result_id,
+ *(guint32 *) &constant->d,
+ *(((guint32 *) &constant->d) + 1) });
+ break;
+
+ case GSK_SL_INT:
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_INT));
+ result_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_DECLARE,
+ 4, GSK_SPV_OP_CONSTANT,
+ (guint32[3]) { type_id,
+ result_id,
+ constant->i32 });
+ break;
+
+ case GSK_SL_UINT:
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_UINT));
+ result_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_DECLARE,
+ 4, GSK_SPV_OP_CONSTANT,
+ (guint32[3]) { type_id,
+ result_id,
+ constant->u32 });
+ break;
+
+ case GSK_SL_BOOL:
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_BOOL));
+ result_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_DECLARE,
+ 3, constant->b ? GSK_SPV_OP_CONSTANT_TRUE : GSK_SPV_OP_CONSTANT_FALSE,
+ (guint32[2]) { type_id,
+ result_id });
+ break;
+
+ case GSK_SL_VOID:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return result_id;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTANT = {
+ gsk_sl_expression_constant_free,
+ gsk_sl_expression_constant_print,
+ gsk_sl_expression_constant_get_return_type,
+ gsk_sl_expression_constant_is_constant,
+ gsk_sl_expression_constant_write_spv
+};
+
+GskSlExpression *
+gsk_sl_expression_parse_constructor_call (GskSlScope *scope,
+ GskSlPreprocessor *stream,
+ GskSlType *type)
+{
+ GskSlExpressionFunctionCall *call;
+ const GskSlToken *token;
+ GskSlType **types;
+ GError *error = NULL;
+ gboolean fail = FALSE;
+ guint i;
+
+ call = gsk_sl_expression_new (GskSlExpressionFunctionCall, &GSK_SL_EXPRESSION_FUNCTION_CALL);
+ call->function = gsk_sl_function_new_constructor (type);
+ g_assert (call->function);
+
+ token = gsk_sl_preprocessor_get (stream);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
+ {
+ gsk_sl_preprocessor_error (stream, "Expected opening \"(\" when calling constructor");
+ gsk_sl_expression_unref ((GskSlExpression *) call);
+ return NULL;
+ }
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
+
+ token = gsk_sl_preprocessor_get (stream);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
+ {
+ GPtrArray *arguments;
+
+ arguments = g_ptr_array_new ();
+ while (TRUE)
+ {
+ GskSlExpression *expression = gsk_sl_expression_parse_assignment (scope, stream);
+
+ if (expression != NULL)
+ g_ptr_array_add (arguments, expression);
+ else
+ fail = TRUE;
+
+ token = gsk_sl_preprocessor_get (stream);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
+ break;
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
+ }
+
+ call->n_arguments = arguments->len;
+ call->arguments = (GskSlExpression **) g_ptr_array_free (arguments, FALSE);
+ }
+
+ 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 (!gsk_sl_function_matches (call->function, types, call->n_arguments, &error))
+ {
+ gsk_sl_preprocessor_error (stream, "%s", error->message);
+ g_clear_error (&error);
+ fail = TRUE;
+ }
+
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
+ {
+ gsk_sl_preprocessor_error (stream, "Expected closing \")\" after arguments.");
+ gsk_sl_expression_unref ((GskSlExpression *) call);
+ return NULL;
+ }
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
+
+ if (fail)
+ {
+ gsk_sl_expression_unref ((GskSlExpression *) call);
+ return NULL;
+ }
+
+ return (GskSlExpression *) call;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_primary (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ GskSlExpressionConstant *constant;
+ const GskSlToken *token;
+
+ token = gsk_sl_preprocessor_get (stream);
+ switch ((guint) token->type)
+ {
+ case GSK_SL_TOKEN_IDENTIFIER:
+ {
+ GskSlExpressionReference *reference;
+ GskSlVariable *variable;
+
+ variable = gsk_sl_scope_lookup_variable (scope, token->str);
+ if (variable == NULL)
+ {
+ gsk_sl_preprocessor_error (stream, "No variable named \"%s\".", token->str);
+ gsk_sl_preprocessor_consume (stream, NULL);
+ return NULL;
+ }
+
+ reference = gsk_sl_expression_new (GskSlExpressionReference, &GSK_SL_EXPRESSION_REFERENCE);
+ reference->variable = gsk_sl_variable_ref (variable);
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) reference);
+ return (GskSlExpression *) reference;
+ }
+
+ case GSK_SL_TOKEN_INTCONSTANT:
+ constant = gsk_sl_expression_new (GskSlExpressionConstant, &GSK_SL_EXPRESSION_CONSTANT);
+ constant->type = GSK_SL_INT;
+ constant->i32 = token->i32;
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) constant);
+ return (GskSlExpression *) constant;
+
+ case GSK_SL_TOKEN_UINTCONSTANT:
+ constant = gsk_sl_expression_new (GskSlExpressionConstant, &GSK_SL_EXPRESSION_CONSTANT);
+ constant->type = GSK_SL_UINT;
+ constant->u32 = token->u32;
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) constant);
+ return (GskSlExpression *) constant;
+
+ case GSK_SL_TOKEN_FLOATCONSTANT:
+ constant = gsk_sl_expression_new (GskSlExpressionConstant, &GSK_SL_EXPRESSION_CONSTANT);
+ constant->type = GSK_SL_FLOAT;
+ constant->f = token->f;
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) constant);
+ return (GskSlExpression *) constant;
+
+ case GSK_SL_TOKEN_BOOLCONSTANT:
+ constant = gsk_sl_expression_new (GskSlExpressionConstant, &GSK_SL_EXPRESSION_CONSTANT);
+ constant->type = GSK_SL_BOOL;
+ constant->b = token->b;
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) constant);
+ return (GskSlExpression *) constant;
+
+ case GSK_SL_TOKEN_DOUBLECONSTANT:
+ constant = gsk_sl_expression_new (GskSlExpressionConstant, &GSK_SL_EXPRESSION_CONSTANT);
+ constant->type = GSK_SL_DOUBLE;
+ constant->d = token->d;
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) constant);
+ return (GskSlExpression *) constant;
+
+ case GSK_SL_TOKEN_VOID:
+ case GSK_SL_TOKEN_FLOAT:
+ case GSK_SL_TOKEN_DOUBLE:
+ case GSK_SL_TOKEN_INT:
+ case GSK_SL_TOKEN_UINT:
+ case GSK_SL_TOKEN_BOOL:
+ case GSK_SL_TOKEN_BVEC2:
+ case GSK_SL_TOKEN_BVEC3:
+ case GSK_SL_TOKEN_BVEC4:
+ case GSK_SL_TOKEN_IVEC2:
+ case GSK_SL_TOKEN_IVEC3:
+ case GSK_SL_TOKEN_IVEC4:
+ case GSK_SL_TOKEN_UVEC2:
+ case GSK_SL_TOKEN_UVEC3:
+ case GSK_SL_TOKEN_UVEC4:
+ case GSK_SL_TOKEN_VEC2:
+ case GSK_SL_TOKEN_VEC3:
+ case GSK_SL_TOKEN_VEC4:
+ case GSK_SL_TOKEN_DVEC2:
+ case GSK_SL_TOKEN_DVEC3:
+ case GSK_SL_TOKEN_DVEC4:
+ case GSK_SL_TOKEN_MAT2:
+ case GSK_SL_TOKEN_MAT3:
+ case GSK_SL_TOKEN_MAT4:
+ case GSK_SL_TOKEN_DMAT2:
+ case GSK_SL_TOKEN_DMAT3:
+ case GSK_SL_TOKEN_DMAT4:
+ case GSK_SL_TOKEN_MAT2X2:
+ case GSK_SL_TOKEN_MAT2X3:
+ case GSK_SL_TOKEN_MAT2X4:
+ case GSK_SL_TOKEN_MAT3X2:
+ case GSK_SL_TOKEN_MAT3X3:
+ case GSK_SL_TOKEN_MAT3X4:
+ case GSK_SL_TOKEN_MAT4X2:
+ case GSK_SL_TOKEN_MAT4X3:
+ case GSK_SL_TOKEN_MAT4X4:
+ case GSK_SL_TOKEN_DMAT2X2:
+ case GSK_SL_TOKEN_DMAT2X3:
+ case GSK_SL_TOKEN_DMAT2X4:
+ case GSK_SL_TOKEN_DMAT3X2:
+ case GSK_SL_TOKEN_DMAT3X3:
+ case GSK_SL_TOKEN_DMAT3X4:
+ case GSK_SL_TOKEN_DMAT4X2:
+ case GSK_SL_TOKEN_DMAT4X3:
+ case GSK_SL_TOKEN_DMAT4X4:
+ {
+ GskSlType *type;
+
+ type = gsk_sl_type_new_parse (stream);
+ if (type == NULL)
+ return NULL;
+
+ return gsk_sl_expression_parse_constructor_call (scope, stream, type);
+ }
+
+ default:
+ gsk_sl_preprocessor_error (stream, "Expected an expression.");
+ gsk_sl_preprocessor_consume (stream, NULL);
+ return NULL;
+ }
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_postfix (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ return gsk_sl_expression_parse_primary (scope, stream);
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_unary (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ return gsk_sl_expression_parse_postfix (scope, stream);
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_multiplicative (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+ GskSlOperation op;
+
+ expression = gsk_sl_expression_parse_unary (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_STAR))
+ op = GSK_SL_OPERATION_MUL;
+ else if (gsk_sl_token_is (token, GSK_SL_TOKEN_SLASH))
+ op = GSK_SL_OPERATION_DIV;
+ else if (gsk_sl_token_is (token, GSK_SL_TOKEN_PERCENT))
+ op = GSK_SL_OPERATION_MOD;
+ else
+ 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_unary (scope, stream);
+ if (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else if ((op == GSK_SL_OPERATION_MOD &&
+ !gsk_sl_expression_bitwise_type_check (stream,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right))) ||
+ (op != GSK_SL_OPERATION_MOD &&
+ !gsk_sl_expression_arithmetic_type_check (stream,
+ FALSE,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right))))
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_additive (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+ GskSlOperation op;
+
+ expression = gsk_sl_expression_parse_multiplicative (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_PLUS))
+ op = GSK_SL_OPERATION_ADD;
+ else if (gsk_sl_token_is (token, GSK_SL_TOKEN_DASH))
+ op = GSK_SL_OPERATION_SUB;
+ else
+ 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 (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else if (!gsk_sl_expression_arithmetic_type_check (stream,
+ FALSE,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right)))
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_shift (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+ GskSlOperation op;
+
+ expression = gsk_sl_expression_parse_additive (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ 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
+ 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 (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else if (!gsk_sl_expression_shift_type_check (stream,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right)))
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_relational (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+ GskSlOperation op;
+
+ expression = gsk_sl_expression_parse_shift (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ 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
+ 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 (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else if (!gsk_sl_expression_relational_type_check (stream,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right)))
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_equality (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+ GskSlOperation op;
+
+ expression = gsk_sl_expression_parse_relational (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ 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
+ 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);
+ if (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_and (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+
+ expression = gsk_sl_expression_parse_equality (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ 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 (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else if (!gsk_sl_expression_bitwise_type_check (stream,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right)))
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_xor (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+
+ expression = gsk_sl_expression_parse_and (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ 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 (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else if (!gsk_sl_expression_bitwise_type_check (stream,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right)))
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_or (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+
+ expression = gsk_sl_expression_parse_xor (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ 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 (operation->right == NULL)
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else if (!gsk_sl_expression_bitwise_type_check (stream,
+ gsk_sl_expression_get_return_type (operation->left),
+ gsk_sl_expression_get_return_type (operation->right)))
+ {
+ gsk_sl_expression_ref (expression);
+ gsk_sl_expression_unref ((GskSlExpression *) operation);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_logical_and (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+
+ expression = gsk_sl_expression_parse_or (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ 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 (operation->right == NULL)
+ {
+ 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 (operation->right)))
+ {
+ gsk_sl_preprocessor_error (stream, "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)))
+ {
+ gsk_sl_preprocessor_error (stream, "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);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_logical_xor (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+
+ expression = gsk_sl_expression_parse_logical_and (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ 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 (operation->right == NULL)
+ {
+ 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 (operation->right)))
+ {
+ gsk_sl_preprocessor_error (stream, "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)))
+ {
+ gsk_sl_preprocessor_error (stream, "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);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_logical_or (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *expression;
+ GskSlExpressionOperation *operation;
+
+ expression = gsk_sl_expression_parse_logical_xor (scope, stream);
+ if (expression == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ 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 (operation->right == NULL)
+ {
+ 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 (operation->right)))
+ {
+ gsk_sl_preprocessor_error (stream, "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)))
+ {
+ gsk_sl_preprocessor_error (stream, "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);
+ }
+ else
+ {
+ expression = (GskSlExpression *) operation;
+ }
+ }
+
+ return expression;
+}
+
+static GskSlExpression *
+gsk_sl_expression_parse_conditional (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ /* XXX: support conditionals */
+ return gsk_sl_expression_parse_logical_or (scope, stream);
+}
+
+GskSlExpression *
+gsk_sl_expression_parse_assignment (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ const GskSlToken *token;
+ GskSlExpression *lvalue;
+ GskSlExpressionAssignment *assign;
+
+ lvalue = gsk_sl_expression_parse_conditional (scope, stream);
+ if (lvalue == NULL)
+ return NULL;
+
+ token = gsk_sl_preprocessor_get (stream);
+ switch ((guint) token->type)
+ {
+ case GSK_SL_TOKEN_EQUAL:
+ case GSK_SL_TOKEN_MUL_ASSIGN:
+ case GSK_SL_TOKEN_DIV_ASSIGN:
+ case GSK_SL_TOKEN_MOD_ASSIGN:
+ case GSK_SL_TOKEN_ADD_ASSIGN:
+ case GSK_SL_TOKEN_SUB_ASSIGN:
+ case GSK_SL_TOKEN_LEFT_ASSIGN:
+ case GSK_SL_TOKEN_RIGHT_ASSIGN:
+ case GSK_SL_TOKEN_AND_ASSIGN:
+ case GSK_SL_TOKEN_XOR_ASSIGN:
+ case GSK_SL_TOKEN_OR_ASSIGN:
+ break;
+
+ default:
+ return lvalue;
+ }
+
+ if (gsk_sl_expression_is_constant (lvalue))
+ {
+ gsk_sl_preprocessor_error (stream, "Cannot assign to a return lvalue.");
+
+ /* Continue parsing like normal here to get more errors */
+ gsk_sl_preprocessor_consume (stream, lvalue);
+ gsk_sl_expression_unref (lvalue);
+
+ return gsk_sl_expression_parse_assignment (scope, stream);
+ }
+
+ assign = gsk_sl_expression_new (GskSlExpressionAssignment, &GSK_SL_EXPRESSION_ASSIGNMENT);
+ assign->lvalue = lvalue;
+ assign->op = token->type;
+
+ gsk_sl_preprocessor_consume (stream, (GskSlExpression *) assign);
+
+ assign->rvalue = gsk_sl_expression_parse_assignment (scope, stream);
+ if (assign->rvalue == NULL)
+ {
+ gsk_sl_expression_unref ((GskSlExpression *) assign);
+ return lvalue;
+ }
+
+ return (GskSlExpression *) assign;
+}
+
+GskSlExpression *
+gsk_sl_expression_parse (GskSlScope *scope,
+ GskSlPreprocessor *stream)
+{
+ /* XXX: Allow comma here */
+ return gsk_sl_expression_parse_assignment (scope, stream);
+}
+
+GskSlExpression *
+gsk_sl_expression_ref (GskSlExpression *expression)
+{
+ g_return_val_if_fail (expression != NULL, NULL);
+
+ expression->ref_count += 1;
+
+ return expression;
+}
+
+void
+gsk_sl_expression_unref (GskSlExpression *expression)
+{
+ if (expression == NULL)
+ return;
+
+ expression->ref_count -= 1;
+ if (expression->ref_count > 0)
+ return;
+
+ expression->class->free (expression);
+}
+
+void
+gsk_sl_expression_print (const GskSlExpression *expression,
+ GString *string)
+{
+ expression->class->print (expression, string);
+}
+
+GskSlType *
+gsk_sl_expression_get_return_type (const GskSlExpression *expression)
+{
+ return expression->class->get_return_type (expression);
+}
+
+gboolean
+gsk_sl_expression_is_constant (const GskSlExpression *expression)
+{
+ return expression->class->is_constant (expression);
+}
+
+guint32
+gsk_sl_expression_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ return expression->class->write_spv (expression, writer);
+}
+
diff --git a/gsk/gskslexpressionprivate.h b/gsk/gskslexpressionprivate.h
new file mode 100644
index 0000000..a526bf3
--- /dev/null
+++ b/gsk/gskslexpressionprivate.h
@@ -0,0 +1,47 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSK_SL_EXPRESSION_PRIVATE_H__
+#define __GSK_SL_EXPRESSION_PRIVATE_H__
+
+#include "gsk/gsksltypesprivate.h"
+
+G_BEGIN_DECLS
+
+GskSlExpression * gsk_sl_expression_parse (GskSlScope *scope,
+ GskSlPreprocessor *stream);
+GskSlExpression * gsk_sl_expression_parse_assignment (GskSlScope *scope,
+ GskSlPreprocessor *stream);
+GskSlExpression * gsk_sl_expression_parse_constructor_call (GskSlScope *scope,
+ GskSlPreprocessor *stream,
+ GskSlType *type);
+
+GskSlExpression * gsk_sl_expression_ref (GskSlExpression *expression);
+void gsk_sl_expression_unref (GskSlExpression *expression);
+
+void gsk_sl_expression_print (const GskSlExpression *expression,
+ GString *string);
+GskSlType * gsk_sl_expression_get_return_type (const GskSlExpression *expression);
+gboolean gsk_sl_expression_is_constant (const GskSlExpression *expression);
+
+guint32 gsk_sl_expression_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer);
+
+G_END_DECLS
+
+#endif /* __GSK_SL_EXPRESSION_PRIVATE_H__ */
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index dfb6e58..6e5fa82 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -20,9 +20,10 @@
#include "gskslnodeprivate.h"
-#include "gskslpreprocessorprivate.h"
+#include "gskslexpressionprivate.h"
#include "gskslfunctionprivate.h"
#include "gskslpointertypeprivate.h"
+#include "gskslpreprocessorprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
@@ -98,20 +99,6 @@ gsk_sl_node_function_print (GskSlNode *node,
g_string_append (string, "}\n");
}
-static GskSlType *
-gsk_sl_node_function_get_return_type (GskSlNode *node)
-{
- GskSlNodeFunction *function = (GskSlNodeFunction *) node;
-
- return function->return_type;
-}
-
-static gboolean
-gsk_sl_node_function_is_constant (GskSlNode *node)
-{
- return TRUE;
-}
-
static guint32
gsk_sl_node_function_write_spv (const GskSlNode *node,
GskSpvWriter *writer)
@@ -162,570 +149,9 @@ gsk_sl_node_function_write_spv (const GskSlNode *node,
static const GskSlNodeClass GSK_SL_NODE_FUNCTION = {
gsk_sl_node_function_free,
gsk_sl_node_function_print,
- gsk_sl_node_function_get_return_type,
- gsk_sl_node_function_is_constant,
gsk_sl_node_function_write_spv
};
-/* ASSIGNMENT */
-
-typedef struct _GskSlNodeAssignment GskSlNodeAssignment;
-
-struct _GskSlNodeAssignment {
- GskSlNode parent;
-
- GskSlTokenType op;
- GskSlNode *lvalue;
- GskSlNode *rvalue;
-};
-
-static void
-gsk_sl_node_assignment_free (GskSlNode *node)
-{
- GskSlNodeAssignment *assignment = (GskSlNodeAssignment *) node;
-
- gsk_sl_node_unref (assignment->lvalue);
- if (assignment->rvalue)
- gsk_sl_node_unref (assignment->rvalue);
-
- g_slice_free (GskSlNodeAssignment, assignment);
-}
-
-static void
-gsk_sl_node_assignment_print (GskSlNode *node,
- GString *string)
-{
- GskSlNodeAssignment *assignment = (GskSlNodeAssignment *) node;
-
- gsk_sl_node_print (assignment->lvalue, string);
-
- switch ((guint) assignment->op)
- {
- case GSK_SL_TOKEN_EQUAL:
- g_string_append (string, " = ");
- break;
- case GSK_SL_TOKEN_MUL_ASSIGN:
- g_string_append (string, " *= ");
- break;
- case GSK_SL_TOKEN_DIV_ASSIGN:
- g_string_append (string, " /= ");
- break;
- case GSK_SL_TOKEN_MOD_ASSIGN:
- g_string_append (string, " %= ");
- break;
- case GSK_SL_TOKEN_ADD_ASSIGN:
- g_string_append (string, " += ");
- break;
- case GSK_SL_TOKEN_SUB_ASSIGN:
- g_string_append (string, " -= ");
- break;
- case GSK_SL_TOKEN_LEFT_ASSIGN:
- g_string_append (string, " <<= ");
- break;
- case GSK_SL_TOKEN_RIGHT_ASSIGN:
- g_string_append (string, " >>= ");
- break;
- case GSK_SL_TOKEN_AND_ASSIGN:
- g_string_append (string, " &= ");
- break;
- case GSK_SL_TOKEN_XOR_ASSIGN:
- g_string_append (string, " ^= ");
- break;
- case GSK_SL_TOKEN_OR_ASSIGN:
- g_string_append (string, " |= ");
- break;
- default:
- g_assert_not_reached ();
- break;
- }
- gsk_sl_node_print (assignment->rvalue, string);
-}
-
-static GskSlType *
-gsk_sl_node_assignment_get_return_type (GskSlNode *node)
-{
- GskSlNodeAssignment *assignment = (GskSlNodeAssignment *) node;
-
- return gsk_sl_node_get_return_type (assignment->lvalue);
-}
-
-static gboolean
-gsk_sl_node_assignment_is_constant (GskSlNode *node)
-{
- //GskSlNodeAssignment *assignment = (GskSlNodeAssignment *) node;
-
- return FALSE;
-}
-
-static guint32
-gsk_sl_node_assignment_write_spv (const GskSlNode *node,
- GskSpvWriter *writer)
-{
- g_assert_not_reached ();
-
- return 0;
-}
-
-static const GskSlNodeClass GSK_SL_NODE_ASSIGNMENT = {
- gsk_sl_node_assignment_free,
- gsk_sl_node_assignment_print,
- gsk_sl_node_assignment_get_return_type,
- gsk_sl_node_assignment_is_constant,
- gsk_sl_node_assignment_write_spv
-};
-
-/* BINARY */
-
-typedef enum {
- GSK_SL_OPERATION_MUL,
- GSK_SL_OPERATION_DIV,
- GSK_SL_OPERATION_MOD,
- GSK_SL_OPERATION_ADD,
- GSK_SL_OPERATION_SUB,
- 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 _GskSlNodeOperation GskSlNodeOperation;
-
-struct _GskSlNodeOperation {
- GskSlNode parent;
-
- GskSlOperation op;
- GskSlNode *left;
- GskSlNode *right;
-};
-
-static void
-gsk_sl_node_operation_free (GskSlNode *node)
-{
- GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
-
- gsk_sl_node_unref (operation->left);
- if (operation->right)
- gsk_sl_node_unref (operation->right);
-
- g_slice_free (GskSlNodeOperation, operation);
-}
-
-static void
-gsk_sl_node_operation_print (GskSlNode *node,
- GString *string)
-{
- const char *op_str[] = {
- [GSK_SL_OPERATION_MUL] = " * ",
- [GSK_SL_OPERATION_DIV] = " / ",
- [GSK_SL_OPERATION_MOD] = " % ",
- [GSK_SL_OPERATION_ADD] = " + ",
- [GSK_SL_OPERATION_SUB] = " - ",
- [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] = " || "
- };
- GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
-
- /* XXX: figure out the need for bracketing here */
-
- gsk_sl_node_print (operation->left, string);
- g_string_append (string, op_str[operation->op]);
- gsk_sl_node_print (operation->right, string);
-}
-
-static GskSlType *
-gsk_sl_node_arithmetic_type_check (GskSlPreprocessor *stream,
- gboolean multiply,
- GskSlType *ltype,
- GskSlType *rtype)
-{
- GskSlScalarType scalar;
-
- if (gsk_sl_scalar_type_can_convert (gsk_sl_type_get_scalar_type (ltype),
- gsk_sl_type_get_scalar_type (rtype)))
- scalar = gsk_sl_type_get_scalar_type (ltype);
- else if (gsk_sl_scalar_type_can_convert (gsk_sl_type_get_scalar_type (rtype),
- gsk_sl_type_get_scalar_type (ltype)))
- scalar = gsk_sl_type_get_scalar_type (rtype);
- else
- {
- if (stream)
- {
- gsk_sl_preprocessor_error (stream, "Operand types %s and %s do not share compatible scalar types.",
- gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
- }
- return NULL;
- }
-
- if (gsk_sl_type_is_matrix (ltype))
- {
- if (gsk_sl_type_is_matrix (rtype))
- {
- if (multiply)
- {
- if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (gsk_sl_type_get_index_type
(rtype)))
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Matrices to multiplication have incompatible
dimensions.");
- return NULL;
- }
- return gsk_sl_type_get_matrix (scalar,
- gsk_sl_type_get_length (gsk_sl_type_get_index_type (ltype)),
- gsk_sl_type_get_length (rtype));
- }
- else
- {
- if (gsk_sl_type_can_convert (ltype, rtype))
- {
- return ltype;
- }
- else if (gsk_sl_type_can_convert (rtype, ltype))
- {
- return rtype;
- }
- else
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Matrix types %s and %s have different size.",
- gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
- return NULL;
- }
- }
- }
- else if (gsk_sl_type_is_vector (rtype))
- {
- if (multiply)
- {
- if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Matrix column count doesn't match vector length.");
- return NULL;
- }
- return gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length (gsk_sl_type_get_index_type
(ltype)));
- }
- else
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Cannot perform arithmetic operation between matrix and
vector.");
- return NULL;
- }
- }
- else if (gsk_sl_type_is_scalar (rtype))
- {
- return gsk_sl_type_get_matrix (scalar,
- gsk_sl_type_get_length (ltype),
- gsk_sl_type_get_length (gsk_sl_type_get_index_type (ltype)));
- }
- else
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Right operand is incompatible type for arithemtic
operation.");
- return NULL;
- }
- }
- else if (gsk_sl_type_is_vector (ltype))
- {
- if (gsk_sl_type_is_matrix (rtype))
- {
- if (multiply)
- {
- if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (gsk_sl_type_get_index_type
(rtype)))
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Vector length for %s doesn't match row count for %s",
- gsk_sl_type_get_name (ltype), gsk_sl_type_get_name
(rtype));
- return NULL;
- }
- return gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length (rtype));
- }
- else
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Cannot perform arithmetic operation between vector and
matrix.");
- return NULL;
- }
- }
- else if (gsk_sl_type_is_vector (rtype))
- {
- if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Vector operands %s and %s to arithmetic operation have
different length.",
- gsk_sl_type_get_name (ltype), gsk_sl_type_get_name
(rtype));
- return NULL;
- }
- return gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length (ltype));
- }
- else if (gsk_sl_type_is_scalar (rtype))
- {
- return gsk_sl_type_get_vector (scalar,
- gsk_sl_type_get_length (ltype));
- }
- else
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Right operand is incompatible type for arithemtic
operation.");
- return NULL;
- }
- }
- else if (gsk_sl_type_is_scalar (ltype))
- {
- if (gsk_sl_type_is_matrix (rtype))
- {
- return gsk_sl_type_get_matrix (scalar,
- gsk_sl_type_get_length (rtype),
- gsk_sl_type_get_length (gsk_sl_type_get_index_type (rtype)));
- }
- else if (gsk_sl_type_is_vector (rtype))
- {
- return gsk_sl_type_get_vector (scalar,
- gsk_sl_type_get_length (rtype));
- }
- else if (gsk_sl_type_is_scalar (rtype))
- {
- return gsk_sl_type_get_scalar (scalar);
- }
- else
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Right operand is incompatible type for arithemtic
operation.");
- return NULL;
- }
- }
- else
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "Left operand is incompatible type for arithemtic operation.");
- return NULL;
- }
-}
-
-static GskSlType *
-gsk_sl_node_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, "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, "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, "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, "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, "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_node_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, "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, "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, "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, "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, "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, "Vector operands do not have the same length.");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-gsk_sl_node_relational_type_check (GskSlPreprocessor *stream,
- GskSlType *ltype,
- GskSlType *rtype)
-{
- if (!gsk_sl_type_is_scalar (ltype))
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, "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, "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, "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, "Right operand to relational operator must not be bool.");
- return FALSE;
- }
-
-
- return TRUE;
-}
-
-static GskSlType *
-gsk_sl_node_operation_get_return_type (GskSlNode *node)
-{
- GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
-
- switch (operation->op)
- {
- case GSK_SL_OPERATION_MUL:
- return gsk_sl_node_arithmetic_type_check (NULL,
- TRUE,
- gsk_sl_node_get_return_type (operation->left),
- gsk_sl_node_get_return_type (operation->right));
- case GSK_SL_OPERATION_DIV:
- case GSK_SL_OPERATION_ADD:
- case GSK_SL_OPERATION_SUB:
- return gsk_sl_node_arithmetic_type_check (NULL,
- FALSE,
- gsk_sl_node_get_return_type (operation->left),
- gsk_sl_node_get_return_type (operation->right));
- case GSK_SL_OPERATION_LSHIFT:
- case GSK_SL_OPERATION_RSHIFT:
- return gsk_sl_node_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_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_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 gboolean
-gsk_sl_node_operation_is_constant (GskSlNode *node)
-{
- GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
-
- return gsk_sl_node_is_constant (operation->left)
- && gsk_sl_node_is_constant (operation->right);
-}
-
-static guint32
-gsk_sl_node_operation_write_spv (const GskSlNode *node,
- GskSpvWriter *writer)
-{
- g_assert_not_reached ();
-
- return 0;
-}
-
-static const GskSlNodeClass GSK_SL_NODE_OPERATION = {
- gsk_sl_node_operation_free,
- gsk_sl_node_operation_print,
- gsk_sl_node_operation_get_return_type,
- gsk_sl_node_operation_is_constant,
- gsk_sl_node_operation_write_spv
-};
-
/* DECLARATION */
typedef struct _GskSlNodeDeclaration GskSlNodeDeclaration;
@@ -734,8 +160,7 @@ struct _GskSlNodeDeclaration {
GskSlNode parent;
GskSlVariable *variable;
- GskSlNode *initial;
- guint constant :1;
+ GskSlExpression *initial;
};
static void
@@ -745,7 +170,7 @@ gsk_sl_node_declaration_free (GskSlNode *node)
gsk_sl_variable_unref (declaration->variable);
if (declaration->initial)
- gsk_sl_node_unref (declaration->initial);
+ gsk_sl_expression_unref (declaration->initial);
g_slice_free (GskSlNodeDeclaration, declaration);
}
@@ -760,26 +185,10 @@ gsk_sl_node_declaration_print (GskSlNode *node,
if (declaration->initial)
{
g_string_append (string, " = ");
- gsk_sl_node_print (declaration->initial, string);
+ gsk_sl_expression_print (declaration->initial, string);
}
}
-static GskSlType *
-gsk_sl_node_declaration_get_return_type (GskSlNode *node)
-{
- GskSlNodeDeclaration *declaration = (GskSlNodeDeclaration *) node;
-
- return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declaration->variable));
-}
-
-static gboolean
-gsk_sl_node_declaration_is_constant (GskSlNode *node)
-{
- GskSlNodeDeclaration *declaration = (GskSlNodeDeclaration *) node;
-
- return declaration->constant;
-}
-
static guint32
gsk_sl_node_declaration_write_spv (const GskSlNode *node,
GskSpvWriter *writer)
@@ -795,7 +204,7 @@ gsk_sl_node_declaration_write_spv (const GskSlNode *node,
GSK_SPV_WRITER_SECTION_CODE,
3, GSK_SPV_OP_STORE,
(guint32[2]) { variable_id,
- gsk_sl_node_write_spv (declaration->initial, writer)});
+ gsk_sl_expression_write_spv (declaration->initial, writer)});
}
return variable_id;
@@ -804,162 +213,9 @@ gsk_sl_node_declaration_write_spv (const GskSlNode *node,
static const GskSlNodeClass GSK_SL_NODE_DECLARATION = {
gsk_sl_node_declaration_free,
gsk_sl_node_declaration_print,
- gsk_sl_node_declaration_get_return_type,
- gsk_sl_node_declaration_is_constant,
gsk_sl_node_declaration_write_spv
};
-/* REFERENCE */
-
-typedef struct _GskSlNodeReference GskSlNodeReference;
-
-struct _GskSlNodeReference {
- GskSlNode parent;
-
- GskSlVariable *variable;
-};
-
-static void
-gsk_sl_node_reference_free (GskSlNode *node)
-{
- GskSlNodeReference *reference = (GskSlNodeReference *) node;
-
- gsk_sl_variable_unref (reference->variable);
-
- g_slice_free (GskSlNodeReference, reference);
-}
-
-static void
-gsk_sl_node_reference_print (GskSlNode *node,
- GString *string)
-{
- GskSlNodeReference *reference = (GskSlNodeReference *) node;
-
- g_string_append (string, gsk_sl_variable_get_name (reference->variable));
-}
-
-static GskSlType *
-gsk_sl_node_reference_get_return_type (GskSlNode *node)
-{
- GskSlNodeReference *reference = (GskSlNodeReference *) node;
-
- return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (reference->variable));
-}
-
-static gboolean
-gsk_sl_node_reference_is_constant (GskSlNode *node)
-{
- return FALSE;
-}
-
-static guint32
-gsk_sl_node_reference_write_spv (const GskSlNode *node,
- GskSpvWriter *writer)
-{
- GskSlNodeReference *reference = (GskSlNodeReference *) node;
- guint32 declaration_id, result_id, type_id;
-
- type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type
(reference->variable)));
- declaration_id = gsk_spv_writer_get_id_for_variable (writer, reference->variable);
- result_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_CODE,
- 4, GSK_SPV_OP_LOAD,
- (guint32[3]) { type_id,
- result_id,
- declaration_id });
-
- return result_id;
-}
-
-static const GskSlNodeClass GSK_SL_NODE_REFERENCE = {
- gsk_sl_node_reference_free,
- gsk_sl_node_reference_print,
- gsk_sl_node_reference_get_return_type,
- gsk_sl_node_reference_is_constant,
- gsk_sl_node_reference_write_spv
-};
-
-/* FUNCTION_CALL */
-
-typedef struct _GskSlNodeFunctionCall GskSlNodeFunctionCall;
-
-struct _GskSlNodeFunctionCall {
- GskSlNode parent;
-
- GskSlFunction *function;
- GskSlNode **arguments;
- guint n_arguments;
-};
-
-static void
-gsk_sl_node_function_call_free (GskSlNode *node)
-{
- GskSlNodeFunctionCall *function_call = (GskSlNodeFunctionCall *) node;
- guint i;
-
- for (i = 0; i < function_call->n_arguments; i++)
- {
- gsk_sl_node_unref (function_call->arguments[i]);
- }
- g_free (function_call->arguments);
-
- gsk_sl_function_unref (function_call->function);
-
- g_slice_free (GskSlNodeFunctionCall, function_call);
-}
-
-static void
-gsk_sl_node_function_call_print (GskSlNode *node,
- GString *string)
-{
- GskSlNodeFunctionCall *function_call = (GskSlNodeFunctionCall *) node;
- guint i;
-
- gsk_sl_function_print_name (function_call->function, string);
- g_string_append (string, " (");
-
- for (i = 0; i < function_call->n_arguments; i++)
- {
- if (i > 0)
- g_string_append (string, ", ");
- gsk_sl_node_print (function_call->arguments[i], string);
- }
-
- g_string_append (string, ")");
-}
-
-static GskSlType *
-gsk_sl_node_function_call_get_return_type (GskSlNode *node)
-{
- GskSlNodeFunctionCall *function_call = (GskSlNodeFunctionCall *) node;
-
- return gsk_sl_function_get_return_type (function_call->function);
-}
-
-static gboolean
-gsk_sl_node_function_call_is_constant (GskSlNode *node)
-{
- return FALSE;
-}
-
-static guint32
-gsk_sl_node_function_call_write_spv (const GskSlNode *node,
- GskSpvWriter *writer)
-{
- g_assert_not_reached ();
-
- return 0;
-}
-
-static const GskSlNodeClass GSK_SL_NODE_FUNCTION_CALL = {
- gsk_sl_node_function_call_free,
- gsk_sl_node_function_call_print,
- gsk_sl_node_function_call_get_return_type,
- gsk_sl_node_function_call_is_constant,
- gsk_sl_node_function_call_write_spv
-};
-
/* RETURN */
typedef struct _GskSlNodeReturn GskSlNodeReturn;
@@ -967,7 +223,7 @@ typedef struct _GskSlNodeReturn GskSlNodeReturn;
struct _GskSlNodeReturn {
GskSlNode parent;
- GskSlNode *value;
+ GskSlExpression *value;
};
static void
@@ -976,7 +232,7 @@ gsk_sl_node_return_free (GskSlNode *node)
GskSlNodeReturn *return_node = (GskSlNodeReturn *) node;
if (return_node->value)
- gsk_sl_node_unref (return_node->value);
+ gsk_sl_expression_unref (return_node->value);
g_slice_free (GskSlNodeReturn, return_node);
}
@@ -991,32 +247,10 @@ gsk_sl_node_return_print (GskSlNode *node,
if (return_node->value)
{
g_string_append (string, " ");
- gsk_sl_node_print (return_node->value, string);
+ gsk_sl_expression_print (return_node->value, string);
}
}
-static GskSlType *
-gsk_sl_node_return_get_return_type (GskSlNode *node)
-{
- GskSlNodeReturn *return_node = (GskSlNodeReturn *) node;
-
- if (return_node->value)
- return gsk_sl_node_get_return_type (return_node->value);
- else
- return NULL;
-}
-
-static gboolean
-gsk_sl_node_return_is_constant (GskSlNode *node)
-{
- GskSlNodeReturn *return_node = (GskSlNodeReturn *) node;
-
- if (return_node->value)
- return gsk_sl_node_is_constant (return_node->value);
- else
- return TRUE;
-}
-
static guint32
gsk_sl_node_return_write_spv (const GskSlNode *node,
GskSpvWriter *writer)
@@ -1029,172 +263,51 @@ gsk_sl_node_return_write_spv (const GskSlNode *node,
static const GskSlNodeClass GSK_SL_NODE_RETURN = {
gsk_sl_node_return_free,
gsk_sl_node_return_print,
- gsk_sl_node_return_get_return_type,
- gsk_sl_node_return_is_constant,
gsk_sl_node_return_write_spv
};
-/* CONSTANT */
-
-typedef struct _GskSlNodeConstant GskSlNodeConstant;
+/* EXPRESSION */
+
+typedef struct _GskSlNodeExpression GskSlNodeExpression;
-struct _GskSlNodeConstant {
+struct _GskSlNodeExpression {
GskSlNode parent;
- GskSlScalarType type;
- union {
- gint32 i32;
- guint32 u32;
- float f;
- double d;
- gboolean b;
- };
+ GskSlExpression *expression;
};
static void
-gsk_sl_node_constant_free (GskSlNode *node)
+gsk_sl_node_expression_free (GskSlNode *node)
{
- GskSlNodeConstant *constant = (GskSlNodeConstant *) node;
-
- g_slice_free (GskSlNodeConstant, constant);
+ GskSlNodeExpression *expression_node = (GskSlNodeExpression *) node;
+
+ gsk_sl_expression_unref (expression_node->expression);
+
+ g_slice_free (GskSlNodeExpression, expression_node);
}
-
+
static void
-gsk_sl_node_constant_print (GskSlNode *node,
- GString *string)
-{
- GskSlNodeConstant *constant = (GskSlNodeConstant *) node;
- char buf[G_ASCII_DTOSTR_BUF_SIZE];
-
- switch (constant->type)
- {
- case GSK_SL_FLOAT:
- g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, constant->f);
- g_string_append (string, buf);
- if (strchr (buf, '.') == NULL)
- g_string_append (string, ".0");
- break;
-
- case GSK_SL_DOUBLE:
- g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, constant->d);
- g_string_append (string, buf);
- if (strchr (buf, '.') == NULL)
- g_string_append (string, ".0");
- g_string_append (string, "lf");
- break;
-
- case GSK_SL_INT:
- g_string_append_printf (string, "%i", (gint) constant->i32);
- break;
-
- case GSK_SL_UINT:
- g_string_append_printf (string, "%uu", (guint) constant->u32);
- break;
-
- case GSK_SL_BOOL:
- g_string_append (string, constant->b ? "true" : "false");
- break;
-
- case GSK_SL_VOID:
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-static GskSlType *
-gsk_sl_node_constant_get_return_type (GskSlNode *node)
+gsk_sl_node_expression_print (GskSlNode *node,
+ GString *string)
{
- GskSlNodeConstant *constant = (GskSlNodeConstant *) node;
-
- return gsk_sl_type_get_scalar (constant->type);
-}
+ GskSlNodeExpression *expression_node = (GskSlNodeExpression *) node;
-static gboolean
-gsk_sl_node_constant_is_constant (GskSlNode *node)
-{
- return TRUE;
+ gsk_sl_expression_print (expression_node->expression, string);
}
-
+
static guint32
-gsk_sl_node_constant_write_spv (const GskSlNode *node,
- GskSpvWriter *writer)
+gsk_sl_node_expression_write_spv (const GskSlNode *node,
+ GskSpvWriter *writer)
{
- GskSlNodeConstant *constant = (GskSlNodeConstant *) node;
- guint32 type_id, result_id;
-
- switch (constant->type)
- {
- case GSK_SL_FLOAT:
- type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_FLOAT));
- result_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_DECLARE,
- 4, GSK_SPV_OP_CONSTANT,
- (guint32[3]) { type_id,
- result_id,
- *(guint32 *) &constant->f });
- break;
-
- case GSK_SL_DOUBLE:
- type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_DOUBLE));
- result_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_DECLARE,
- 5, GSK_SPV_OP_CONSTANT,
- (guint32[4]) { type_id,
- result_id,
- *(guint32 *) &constant->d,
- *(((guint32 *) &constant->d) + 1) });
- break;
-
- case GSK_SL_INT:
- type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_INT));
- result_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_DECLARE,
- 4, GSK_SPV_OP_CONSTANT,
- (guint32[3]) { type_id,
- result_id,
- constant->i32 });
- break;
-
- case GSK_SL_UINT:
- type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_UINT));
- result_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_DECLARE,
- 4, GSK_SPV_OP_CONSTANT,
- (guint32[3]) { type_id,
- result_id,
- constant->u32 });
- break;
-
- case GSK_SL_BOOL:
- type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (GSK_SL_BOOL));
- result_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_DECLARE,
- 3, constant->b ? GSK_SPV_OP_CONSTANT_TRUE : GSK_SPV_OP_CONSTANT_FALSE,
- (guint32[2]) { type_id,
- result_id });
- break;
-
- case GSK_SL_VOID:
- default:
- g_assert_not_reached ();
- break;
- }
-
- return result_id;
-}
+ GskSlNodeExpression *expression_node = (GskSlNodeExpression *) node;
-static const GskSlNodeClass GSK_SL_NODE_CONSTANT = {
- gsk_sl_node_constant_free,
- gsk_sl_node_constant_print,
- gsk_sl_node_constant_get_return_type,
- gsk_sl_node_constant_is_constant,
- gsk_sl_node_constant_write_spv
+ return gsk_sl_expression_write_spv (expression_node->expression, writer);
+}
+
+static const GskSlNodeClass GSK_SL_NODE_EXPRESSION = {
+ gsk_sl_node_expression_free,
+ gsk_sl_node_expression_print,
+ gsk_sl_node_expression_write_spv
};
/* API */
@@ -1246,847 +359,6 @@ gsk_sl_node_parse_function_prototype (GskSlScope *scope,
}
static GskSlNode *
-gsk_sl_node_parse_assignment_expression (GskSlScope *scope,
- GskSlPreprocessor *stream);
-
-static GskSlNode *
-gsk_sl_node_parse_constructor_call (GskSlScope *scope,
- GskSlPreprocessor *stream,
- GskSlType *type)
-{
- GskSlNodeFunctionCall *call;
- const GskSlToken *token;
- GskSlType **types;
- GError *error = NULL;
- gboolean fail = FALSE;
- guint i;
-
- call = gsk_sl_node_new (GskSlNodeFunctionCall, &GSK_SL_NODE_FUNCTION_CALL);
- call->function = gsk_sl_function_new_constructor (type);
- g_assert (call->function);
-
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
- {
- gsk_sl_preprocessor_error (stream, "Expected opening \"(\" when calling constructor");
- gsk_sl_node_unref ((GskSlNode *) call);
- return NULL;
- }
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) call);
-
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
- {
- GPtrArray *arguments;
-
- arguments = g_ptr_array_new ();
- while (TRUE)
- {
- GskSlNode *node = gsk_sl_node_parse_assignment_expression (scope, stream);
-
- if (node != NULL)
- g_ptr_array_add (arguments, node);
- else
- fail = TRUE;
-
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
- break;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) call);
- }
-
- call->n_arguments = arguments->len;
- call->arguments = (GskSlNode **) g_ptr_array_free (arguments, FALSE);
- }
-
- types = g_newa (GskSlType *, call->n_arguments);
- for (i = 0; i < call->n_arguments; i++)
- types[i] = gsk_sl_node_get_return_type (call->arguments[i]);
- if (!gsk_sl_function_matches (call->function, types, call->n_arguments, &error))
- {
- gsk_sl_preprocessor_error (stream, "%s", error->message);
- g_clear_error (&error);
- fail = TRUE;
- }
-
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
- {
- gsk_sl_preprocessor_error (stream, "Expected closing \")\" after arguments.");
- gsk_sl_node_unref ((GskSlNode *) call);
- return NULL;
- }
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) call);
-
- if (fail)
- {
- gsk_sl_node_unref ((GskSlNode *) call);
- return NULL;
- }
-
- return (GskSlNode *) call;
-}
-
-static GskSlNode *
-gsk_sl_node_parse_primary_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- GskSlNodeConstant *constant;
- const GskSlToken *token;
-
- token = gsk_sl_preprocessor_get (stream);
- switch ((guint) token->type)
- {
- case GSK_SL_TOKEN_IDENTIFIER:
- {
- GskSlNodeReference *reference;
- GskSlVariable *variable;
-
- variable = gsk_sl_scope_lookup_variable (scope, token->str);
- if (variable == NULL)
- {
- gsk_sl_preprocessor_error (stream, "No variable named \"%s\".", token->str);
- gsk_sl_preprocessor_consume (stream, NULL);
- return NULL;
- }
-
- reference = gsk_sl_node_new (GskSlNodeReference, &GSK_SL_NODE_REFERENCE);
- reference->variable = gsk_sl_variable_ref (variable);
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) reference);
- return (GskSlNode *) reference;
- }
-
- case GSK_SL_TOKEN_INTCONSTANT:
- constant = gsk_sl_node_new (GskSlNodeConstant, &GSK_SL_NODE_CONSTANT);
- constant->type = GSK_SL_INT;
- constant->i32 = token->i32;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) constant);
- return (GskSlNode *) constant;
-
- case GSK_SL_TOKEN_UINTCONSTANT:
- constant = gsk_sl_node_new (GskSlNodeConstant, &GSK_SL_NODE_CONSTANT);
- constant->type = GSK_SL_UINT;
- constant->u32 = token->u32;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) constant);
- return (GskSlNode *) constant;
-
- case GSK_SL_TOKEN_FLOATCONSTANT:
- constant = gsk_sl_node_new (GskSlNodeConstant, &GSK_SL_NODE_CONSTANT);
- constant->type = GSK_SL_FLOAT;
- constant->f = token->f;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) constant);
- return (GskSlNode *) constant;
-
- case GSK_SL_TOKEN_BOOLCONSTANT:
- constant = gsk_sl_node_new (GskSlNodeConstant, &GSK_SL_NODE_CONSTANT);
- constant->type = GSK_SL_BOOL;
- constant->b = token->b;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) constant);
- return (GskSlNode *) constant;
-
- case GSK_SL_TOKEN_DOUBLECONSTANT:
- constant = gsk_sl_node_new (GskSlNodeConstant, &GSK_SL_NODE_CONSTANT);
- constant->type = GSK_SL_DOUBLE;
- constant->d = token->d;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) constant);
- return (GskSlNode *) constant;
-
- case GSK_SL_TOKEN_VOID:
- case GSK_SL_TOKEN_FLOAT:
- case GSK_SL_TOKEN_DOUBLE:
- case GSK_SL_TOKEN_INT:
- case GSK_SL_TOKEN_UINT:
- case GSK_SL_TOKEN_BOOL:
- case GSK_SL_TOKEN_BVEC2:
- case GSK_SL_TOKEN_BVEC3:
- case GSK_SL_TOKEN_BVEC4:
- case GSK_SL_TOKEN_IVEC2:
- case GSK_SL_TOKEN_IVEC3:
- case GSK_SL_TOKEN_IVEC4:
- case GSK_SL_TOKEN_UVEC2:
- case GSK_SL_TOKEN_UVEC3:
- case GSK_SL_TOKEN_UVEC4:
- case GSK_SL_TOKEN_VEC2:
- case GSK_SL_TOKEN_VEC3:
- case GSK_SL_TOKEN_VEC4:
- case GSK_SL_TOKEN_DVEC2:
- case GSK_SL_TOKEN_DVEC3:
- case GSK_SL_TOKEN_DVEC4:
- case GSK_SL_TOKEN_MAT2:
- case GSK_SL_TOKEN_MAT3:
- case GSK_SL_TOKEN_MAT4:
- case GSK_SL_TOKEN_DMAT2:
- case GSK_SL_TOKEN_DMAT3:
- case GSK_SL_TOKEN_DMAT4:
- case GSK_SL_TOKEN_MAT2X2:
- case GSK_SL_TOKEN_MAT2X3:
- case GSK_SL_TOKEN_MAT2X4:
- case GSK_SL_TOKEN_MAT3X2:
- case GSK_SL_TOKEN_MAT3X3:
- case GSK_SL_TOKEN_MAT3X4:
- case GSK_SL_TOKEN_MAT4X2:
- case GSK_SL_TOKEN_MAT4X3:
- case GSK_SL_TOKEN_MAT4X4:
- case GSK_SL_TOKEN_DMAT2X2:
- case GSK_SL_TOKEN_DMAT2X3:
- case GSK_SL_TOKEN_DMAT2X4:
- case GSK_SL_TOKEN_DMAT3X2:
- case GSK_SL_TOKEN_DMAT3X3:
- case GSK_SL_TOKEN_DMAT3X4:
- case GSK_SL_TOKEN_DMAT4X2:
- case GSK_SL_TOKEN_DMAT4X3:
- case GSK_SL_TOKEN_DMAT4X4:
- {
- GskSlType *type;
-
- type = gsk_sl_type_new_parse (stream);
- if (type == NULL)
- return NULL;
-
- return gsk_sl_node_parse_constructor_call (scope, stream, type);
- }
-
- default:
- gsk_sl_preprocessor_error (stream, "Expected an expression.");
- gsk_sl_preprocessor_consume (stream, NULL);
- return NULL;
- }
-}
-
-static GskSlNode *
-gsk_sl_node_parse_postfix_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- return gsk_sl_node_parse_primary_expression (scope, stream);
-}
-
-static GskSlNode *
-gsk_sl_node_parse_unary_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- return gsk_sl_node_parse_postfix_expression (scope, stream);
-}
-
-static GskSlNode *
-gsk_sl_node_parse_multiplicative_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
- GskSlOperation op;
-
- node = gsk_sl_node_parse_unary_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- while (TRUE)
- {
- token = gsk_sl_preprocessor_get (stream);
- if (gsk_sl_token_is (token, GSK_SL_TOKEN_STAR))
- op = GSK_SL_OPERATION_MUL;
- else if (gsk_sl_token_is (token, GSK_SL_TOKEN_SLASH))
- op = GSK_SL_OPERATION_DIV;
- else if (gsk_sl_token_is (token, GSK_SL_TOKEN_PERCENT))
- op = GSK_SL_OPERATION_MOD;
- else
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = op;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_unary_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if ((op == GSK_SL_OPERATION_MOD &&
- !gsk_sl_node_bitwise_type_check (stream,
- gsk_sl_node_get_return_type (operation->left),
- gsk_sl_node_get_return_type (operation->right))) ||
- (op != GSK_SL_OPERATION_MOD &&
- !gsk_sl_node_arithmetic_type_check (stream,
- FALSE,
- 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_additive_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
- GskSlOperation op;
-
- node = gsk_sl_node_parse_multiplicative_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- while (TRUE)
- {
- token = gsk_sl_preprocessor_get (stream);
- if (gsk_sl_token_is (token, GSK_SL_TOKEN_PLUS))
- op = GSK_SL_OPERATION_ADD;
- else if (gsk_sl_token_is (token, GSK_SL_TOKEN_DASH))
- op = GSK_SL_OPERATION_SUB;
- else
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = op;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_additive_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_node_arithmetic_type_check (stream,
- FALSE,
- 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_shift_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
- GskSlOperation op;
-
- node = gsk_sl_node_parse_additive_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- 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
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = op;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_additive_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_node_shift_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_relational_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
- GskSlOperation op;
-
- node = gsk_sl_node_parse_shift_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- 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
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = op;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_shift_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_node_relational_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_equality_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
- GskSlOperation op;
-
- node = gsk_sl_node_parse_relational_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- 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
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = op;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_relational_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else
- {
- node = (GskSlNode *) operation;
- }
- }
-
- return node;
-}
-
-static GskSlNode *
-gsk_sl_node_parse_and_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
-
- node = gsk_sl_node_parse_equality_expression (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 (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 (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
-
- node = gsk_sl_node_parse_and_expression (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 (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 (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
-
- node = gsk_sl_node_parse_xor_expression (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 (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_logical_and_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
-
- node = gsk_sl_node_parse_or_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- while (TRUE)
- {
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_AND_OP))
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = GSK_SL_OPERATION_LOGICAL_AND;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_or_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
- gsk_sl_node_get_return_type (operation->right)))
- {
- gsk_sl_preprocessor_error (stream, "Right operand of && expression is not bool but %s",
- gsk_sl_type_get_name (gsk_sl_node_get_return_type
(operation->right)));
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
- gsk_sl_node_get_return_type (node)))
- {
- gsk_sl_preprocessor_error (stream, "Left operand of && expression is not bool but %s",
- gsk_sl_type_get_name (gsk_sl_node_get_return_type (node)));
- node = 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_logical_xor_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
-
- node = gsk_sl_node_parse_logical_and_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- while (TRUE)
- {
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_XOR_OP))
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = GSK_SL_OPERATION_LOGICAL_XOR;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_logical_and_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
- gsk_sl_node_get_return_type (operation->right)))
- {
- gsk_sl_preprocessor_error (stream, "Right operand of ^^ expression is not bool but %s",
- gsk_sl_type_get_name (gsk_sl_node_get_return_type
(operation->right)));
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
- gsk_sl_node_get_return_type (node)))
- {
- gsk_sl_preprocessor_error (stream, "Left operand of ^^ expression is not bool but %s",
- gsk_sl_type_get_name (gsk_sl_node_get_return_type (node)));
- node = 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_logical_or_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *node;
- GskSlNodeOperation *operation;
-
- node = gsk_sl_node_parse_logical_xor_expression (scope, stream);
- if (node == NULL)
- return NULL;
-
- while (TRUE)
- {
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_OR_OP))
- return node;
-
- operation = gsk_sl_node_new (GskSlNodeOperation, &GSK_SL_NODE_OPERATION);
- operation->left = node;
- operation->op = GSK_SL_OPERATION_LOGICAL_OR;
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) operation);
- operation->right = gsk_sl_node_parse_logical_xor_expression (scope, stream);
- if (operation->right == NULL)
- {
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
- gsk_sl_node_get_return_type (operation->right)))
- {
- gsk_sl_preprocessor_error (stream, "Right operand of || expression is not bool but %s",
- gsk_sl_type_get_name (gsk_sl_node_get_return_type
(operation->right)));
- gsk_sl_node_ref (node);
- gsk_sl_node_unref ((GskSlNode *) operation);
- }
- else if (!gsk_sl_type_can_convert (gsk_sl_type_get_scalar (GSK_SL_BOOL),
- gsk_sl_node_get_return_type (node)))
- {
- gsk_sl_preprocessor_error (stream, "Left operand of || expression is not bool but %s",
- gsk_sl_type_get_name (gsk_sl_node_get_return_type (node)));
- node = 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_conditional_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- /* XXX: support conditionals */
- return gsk_sl_node_parse_logical_or_expression (scope, stream);
-}
-
-static GskSlNode *
-gsk_sl_node_parse_assignment_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- const GskSlToken *token;
- GskSlNode *lvalue;
- GskSlNodeAssignment *assign;
-
- lvalue = gsk_sl_node_parse_conditional_expression (scope, stream);
- if (lvalue == NULL)
- return NULL;
-
- token = gsk_sl_preprocessor_get (stream);
- switch ((guint) token->type)
- {
- case GSK_SL_TOKEN_EQUAL:
- case GSK_SL_TOKEN_MUL_ASSIGN:
- case GSK_SL_TOKEN_DIV_ASSIGN:
- case GSK_SL_TOKEN_MOD_ASSIGN:
- case GSK_SL_TOKEN_ADD_ASSIGN:
- case GSK_SL_TOKEN_SUB_ASSIGN:
- case GSK_SL_TOKEN_LEFT_ASSIGN:
- case GSK_SL_TOKEN_RIGHT_ASSIGN:
- case GSK_SL_TOKEN_AND_ASSIGN:
- case GSK_SL_TOKEN_XOR_ASSIGN:
- case GSK_SL_TOKEN_OR_ASSIGN:
- break;
-
- default:
- return lvalue;
- }
-
- if (gsk_sl_node_is_constant (lvalue))
- {
- gsk_sl_preprocessor_error (stream, "Cannot assign to a return lvalue.");
-
- /* Continue parsing like normal here to get more errors */
- gsk_sl_preprocessor_consume (stream, lvalue);
- gsk_sl_node_unref (lvalue);
-
- return gsk_sl_node_parse_assignment_expression (scope, stream);
- }
-
- assign = gsk_sl_node_new (GskSlNodeAssignment, &GSK_SL_NODE_ASSIGNMENT);
- assign->lvalue = lvalue;
- assign->op = token->type;
-
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) assign);
-
- assign->rvalue = gsk_sl_node_parse_assignment_expression (scope, stream);
- if (assign->rvalue == NULL)
- {
- gsk_sl_node_unref ((GskSlNode *) assign);
- return lvalue;
- }
-
- return (GskSlNode *) assign;
-}
-
-static GskSlNode *
-gsk_sl_node_parse_expression (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- /* XXX: Allow comma here */
- return gsk_sl_node_parse_assignment_expression (scope, stream);
-}
-
-static GskSlNode *
gsk_sl_node_parse_declaration (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlPointerType *type)
@@ -2110,7 +382,7 @@ gsk_sl_node_parse_declaration (GskSlScope *scope,
if (gsk_sl_token_is (token, GSK_SL_TOKEN_EQUAL))
{
gsk_sl_preprocessor_consume (stream, (GskSlNode *) declaration);
- declaration->initial = gsk_sl_node_parse_assignment_expression (scope, stream);
+ declaration->initial = gsk_sl_expression_parse_assignment (scope, stream);
}
gsk_sl_scope_add_variable (scope, declaration->variable);
@@ -2124,7 +396,6 @@ gsk_sl_node_parse_function_definition (GskSlScope *scope,
{
GskSlNodeFunction *function;
const GskSlToken *token;
- GskSlNode *node;
gboolean result = TRUE;
function = gsk_sl_node_parse_function_prototype (scope, stream);
@@ -2223,6 +494,7 @@ gsk_sl_node_parse_function_definition (GskSlScope *scope,
GskSlType *type;
GskSlPointerTypeFlags flags;
gboolean success;
+ GskSlNode *node = NULL;
success = gsk_sl_type_qualifier_parse (stream,
GSK_SL_POINTER_TYPE_PARAMETER_QUALIFIER
@@ -2237,7 +509,21 @@ gsk_sl_node_parse_function_definition (GskSlScope *scope,
if (token->type == GSK_SL_TOKEN_LEFT_BRACE)
{
- node = gsk_sl_node_parse_constructor_call (function->scope, stream, type);
+ GskSlExpression *expression = gsk_sl_expression_parse_constructor_call (function->scope,
stream, type);
+
+ if (expression)
+ {
+ GskSlNodeExpression *node;
+
+ node = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
+ node->expression = expression;
+
+ function->statements = g_slist_append (function->statements, node);
+ }
+ else
+ {
+ node = NULL;
+ }
}
else
{
@@ -2249,7 +535,7 @@ gsk_sl_node_parse_function_definition (GskSlScope *scope,
}
gsk_sl_type_unref (type);
-
+
if (!success)
{
gsk_sl_node_unref (node);
@@ -2270,7 +556,7 @@ gsk_sl_node_parse_function_definition (GskSlScope *scope,
token = gsk_sl_preprocessor_get (stream);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
{
- return_node->value = gsk_sl_node_parse_expression (function->scope, stream);
+ return_node->value = gsk_sl_expression_parse (function->scope, stream);
if (return_node->value == NULL)
{
gsk_sl_node_unref ((GskSlNode *) return_node);
@@ -2282,10 +568,10 @@ gsk_sl_node_parse_function_definition (GskSlScope *scope,
gsk_sl_node_unref ((GskSlNode *) return_node);
break;
}
- else if (!gsk_sl_type_can_convert (function->return_type, gsk_sl_node_get_return_type
(return_node->value)))
+ else if (!gsk_sl_type_can_convert (function->return_type, gsk_sl_expression_get_return_type
(return_node->value)))
{
gsk_sl_preprocessor_error (stream, "Cannot convert return type %s to function type %s.",
- gsk_sl_type_get_name (gsk_sl_node_get_return_type
(return_node->value)),
+ gsk_sl_type_get_name (gsk_sl_expression_get_return_type
(return_node->value)),
gsk_sl_type_get_name (function->return_type));
gsk_sl_node_unref ((GskSlNode *) return_node);
break;
@@ -2305,11 +591,23 @@ gsk_sl_node_parse_function_definition (GskSlScope *scope,
break;
default:
- node = gsk_sl_node_parse_expression (function->scope, stream);
- if (node)
- function->statements = g_slist_append (function->statements, node);
- else
- result = FALSE;
+ {
+ GskSlExpression * expression = gsk_sl_expression_parse (function->scope, stream);
+
+ if (expression)
+ {
+ GskSlNodeExpression *node;
+
+ node = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
+ node->expression = expression;
+
+ function->statements = g_slist_append (function->statements, node);
+ }
+ else
+ {
+ result = FALSE;
+ }
+ }
break;
}
}
@@ -2358,18 +656,6 @@ gsk_sl_node_print (GskSlNode *node,
node->class->print (node, string);
}
-GskSlType *
-gsk_sl_node_get_return_type (GskSlNode *node)
-{
- return node->class->get_return_type (node);
-}
-
-gboolean
-gsk_sl_node_is_constant (GskSlNode *node)
-{
- return node->class->is_constant (node);
-}
-
guint32
gsk_sl_node_write_spv (const GskSlNode *node,
GskSpvWriter *writer)
diff --git a/gsk/gskslnodeprivate.h b/gsk/gskslnodeprivate.h
index ae99dcb..ead2280 100644
--- a/gsk/gskslnodeprivate.h
+++ b/gsk/gskslnodeprivate.h
@@ -37,8 +37,6 @@ struct _GskSlNodeClass {
void (* print) (GskSlNode *node,
GString *string);
- GskSlType * (* get_return_type) (GskSlNode *node);
- gboolean (* is_constant) (GskSlNode *node);
guint32 (* write_spv) (const GskSlNode *node,
GskSpvWriter *writer);
};
@@ -51,8 +49,6 @@ void gsk_sl_node_unref (GskSlNode
void gsk_sl_node_print (GskSlNode *node,
GString *string);
-GskSlType * gsk_sl_node_get_return_type (GskSlNode *node);
-gboolean gsk_sl_node_is_constant (GskSlNode *node);
guint32 gsk_sl_node_write_spv (const GskSlNode *node,
GskSpvWriter *writer);
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index 98c76f6..ee5af2a 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -365,7 +365,7 @@ gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc)
void
gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
- GskSlNode *consumer)
+ gpointer consumer)
{
gsk_sl_preprocessor_ensure (preproc);
diff --git a/gsk/gskslpreprocessorprivate.h b/gsk/gskslpreprocessorprivate.h
index acb7d22..b188b23 100644
--- a/gsk/gskslpreprocessorprivate.h
+++ b/gsk/gskslpreprocessorprivate.h
@@ -35,7 +35,7 @@ void gsk_sl_preprocessor_unref (GskSlPreprocess
const GskSlToken * gsk_sl_preprocessor_get (GskSlPreprocessor *preproc);
const GskCodeLocation * gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc);
void gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
- GskSlNode *consumer);
+ gpointer consumer);
void gsk_sl_preprocessor_error (GskSlPreprocessor *preproc,
const char *format,
diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c
index 507112b..dcb0f99 100644
--- a/gsk/gskslprogram.c
+++ b/gsk/gskslprogram.c
@@ -121,7 +121,7 @@ gsk_sl_program_write_spv (GskSlProgram *program,
#if 0
for (l = program->functions; l; l = l->next)
{
- guint32 id = gsk_sl_node_write_spv (l->data, writer);
+ guint32 id = gsk_sl_function_write_spv (l->data, writer);
if (g_str_equal (((GskSlNodeFunction *) l->data)->name, "main"))
gsk_spv_writer_set_entry_point (writer, id);
diff --git a/gsk/gsksltypesprivate.h b/gsk/gsksltypesprivate.h
index f02703b..d99118a 100644
--- a/gsk/gsksltypesprivate.h
+++ b/gsk/gsksltypesprivate.h
@@ -21,6 +21,7 @@
#include <gsk/gsktypes.h>
+typedef struct _GskSlExpression GskSlExpression;
typedef struct _GskSlFunction GskSlFunction;
typedef struct _GskSlNode GskSlNode;
typedef struct _GskSlPreprocessor GskSlPreprocessor;
diff --git a/gsk/meson.build b/gsk/meson.build
index cda34e5..2cc6431 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -35,6 +35,7 @@ gsk_private_sources = files([
'gskprofiler.c',
'gskshaderbuilder.c',
'gsksldefine.c',
+ 'gskslexpression.c',
'gskslfunction.c',
'gskslnode.c',
'gskslpreprocessor.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]