[gtk+/wip/otte/shader: 2/44] gskslexpression: Split multiplication from other binary operations
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 2/44] gskslexpression: Split multiplication from other binary operations
- Date: Thu, 12 Oct 2017 00:57:40 +0000 (UTC)
commit 9c093098306ebe0398b1ee6287d6da579d05bd0c
Author: Benjamin Otte <otte redhat com>
Date: Wed Oct 4 00:07:35 2017 +0200
gskslexpression: Split multiplication from other binary operations
Also implement get_constant() and write_spv() vfuncs.
gsk/gskslexpression.c | 686 ++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 591 insertions(+), 95 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 81b2462..0ba77ce 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -171,10 +171,524 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_ASSIGNMENT = {
gsk_sl_expression_assignment_write_spv
};
-/* BINARY */
+/* MULTIPLICATION */
+
+typedef struct _GskSlExpressionMultiplication GskSlExpressionMultiplication;
+
+struct _GskSlExpressionMultiplication {
+ GskSlExpression parent;
+
+ GskSlType *type;
+ GskSlExpression *left;
+ GskSlExpression *right;
+};
+
+static void
+gsk_sl_expression_multiplication_free (GskSlExpression *expression)
+{
+ GskSlExpressionMultiplication *multiplication = (GskSlExpressionMultiplication *) expression;
+
+ gsk_sl_expression_unref (multiplication->left);
+ gsk_sl_expression_unref (multiplication->right);
+ gsk_sl_type_unref (multiplication->type);
+
+ g_slice_free (GskSlExpressionMultiplication, multiplication);
+}
+
+static void
+gsk_sl_expression_multiplication_print (const GskSlExpression *expression,
+ GskSlPrinter *printer)
+{
+ GskSlExpressionMultiplication *multiplication = (GskSlExpressionMultiplication *) expression;
+
+ gsk_sl_expression_print (multiplication->left, printer);
+ gsk_sl_printer_append (printer, " * ");
+ gsk_sl_expression_print (multiplication->right, printer);
+}
+
+static GskSlType *
+gsk_sl_expression_multiplication_get_result_type (GskSlPreprocessor *preproc,
+ 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
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+ "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 (scalar == GSK_SL_BOOL)
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Cannot multiply booleans.");
+ return NULL;
+ }
+
+ if (gsk_sl_type_is_matrix (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (gsk_sl_type_get_index_type (rtype)))
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+ "Incompatible dimensions when multiplying %s * %s.",
+ gsk_sl_type_get_name (ltype),
+ gsk_sl_type_get_name (rtype));
+ return NULL;
+ }
+ return gsk_sl_type_get_matrix (scalar,
+ gsk_sl_type_get_length (rtype),
+ gsk_sl_type_get_length (gsk_sl_type_get_index_type (ltype)));
+ }
+ else if (gsk_sl_type_is_vector (rtype))
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+ "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 (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
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+ "Right operand is incompatible type for multiplication.");
+ return NULL;
+ }
+ }
+ else if (gsk_sl_type_is_vector (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (gsk_sl_type_get_index_type (rtype)))
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+ "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 (gsk_sl_type_is_vector (rtype))
+ {
+ if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+ "Vector operands %s and %s to arithmetic multiplication 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
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
+ "Right operand is incompatible type for multiplication.");
+ 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
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Right operand is incompatible type for
multiplication.");
+ return NULL;
+ }
+ }
+ else
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Left operand is incompatible type for
multiplication.");
+ return NULL;
+ }
+}
+
+static GskSlType *
+gsk_sl_expression_multiplication_get_return_type (const GskSlExpression *expression)
+{
+ GskSlExpressionMultiplication *multiplication = (GskSlExpressionMultiplication *) expression;
+
+ return multiplication->type;
+}
+
+#define GSK_SL_OPERATION_FUNC_SCALAR(func,type,...) \
+static void \
+func (gpointer value, gpointer scalar) \
+{ \
+ type x = *(type *) value; \
+ type y = *(type *) scalar; \
+ __VA_ARGS__ \
+ *(type *) value = x; \
+}
+GSK_SL_OPERATION_FUNC_SCALAR(gsk_sl_expression_multiplication_int, gint32, x *= y;)
+GSK_SL_OPERATION_FUNC_SCALAR(gsk_sl_expression_multiplication_uint, guint32, x *= y;)
+GSK_SL_OPERATION_FUNC_SCALAR(gsk_sl_expression_multiplication_float, float, x *= y;)
+GSK_SL_OPERATION_FUNC_SCALAR(gsk_sl_expression_multiplication_double, double, x *= y;)
+static void (* mult_funcs[]) (gpointer, gpointer) = {
+ [GSK_SL_INT] = gsk_sl_expression_multiplication_int,
+ [GSK_SL_UINT] = gsk_sl_expression_multiplication_uint,
+ [GSK_SL_FLOAT] = gsk_sl_expression_multiplication_float,
+ [GSK_SL_DOUBLE] = gsk_sl_expression_multiplication_double,
+};
+
+static GskSlValue *
+gsk_sl_expression_multiplication_get_constant (const GskSlExpression *expression)
+{
+ const GskSlExpressionMultiplication *multiplication = (const GskSlExpressionMultiplication *) expression;
+ GskSlValue *result, *lvalue, *rvalue;
+ GskSlType *ltype, *rtype;
+ GskSlScalarType scalar;
+
+ scalar = gsk_sl_type_get_scalar_type (multiplication->type);
+ lvalue = gsk_sl_expression_get_constant (multiplication->left);
+ if (lvalue == NULL)
+ return NULL;
+ rvalue = gsk_sl_expression_get_constant (multiplication->right);
+ if (rvalue == NULL)
+ {
+ gsk_sl_value_free (lvalue);
+ return NULL;
+ }
+ lvalue = gsk_sl_value_convert_components (lvalue, scalar);
+ rvalue = gsk_sl_value_convert_components (rvalue, scalar);
+ ltype = gsk_sl_value_get_type (lvalue);
+ rtype = gsk_sl_value_get_type (rvalue);
+
+ if ((gsk_sl_type_is_matrix (rtype) && gsk_sl_type_is_matrix (ltype)) ||
+ (gsk_sl_type_is_vector (rtype) && gsk_sl_type_is_matrix (ltype)) ||
+ (gsk_sl_type_is_matrix (rtype) && gsk_sl_type_is_vector (ltype)))
+ {
+ gsize c, cols;
+ gsize r, rows;
+ gsize i, n;
+ gpointer data, ldata, rdata;
+
+ result = gsk_sl_value_new (multiplication->type);
+ data = gsk_sl_value_get_data (result);
+ ldata = gsk_sl_value_get_data (lvalue);
+ rdata = gsk_sl_value_get_data (rvalue);
+
+ if (gsk_sl_type_is_vector (rtype))
+ {
+ cols = 1;
+ rows = gsk_sl_type_get_length (gsk_sl_value_get_type (result));
+ n = gsk_sl_type_get_length (rtype);
+ }
+ else if (gsk_sl_type_is_vector (ltype))
+ {
+ cols = gsk_sl_type_get_length (gsk_sl_value_get_type (result));
+ rows = 1;
+ n = gsk_sl_type_get_length (ltype);
+ }
+ else
+ {
+ cols = gsk_sl_type_get_length (gsk_sl_value_get_type (result));
+ rows = gsk_sl_type_get_length (gsk_sl_type_get_index_type (gsk_sl_value_get_type (result)));
+ n = gsk_sl_type_get_length (ltype);
+ }
+#define MATRIXMULT(TYPE) G_STMT_START{\
+ for (c = 0; c < cols; c++) \
+ { \
+ for (r = 0; r < rows; r++) \
+ { \
+ TYPE result = 0; \
+ for (i = 0; i < n; i++) \
+ { \
+ result += *((TYPE *) rdata + c * n + i) * \
+ *((TYPE *) ldata + i * rows + r); \
+ } \
+ *((TYPE *) data + c * rows + r) = result; \
+ } \
+ } \
+ }G_STMT_END
+ if (gsk_sl_type_get_scalar_type (multiplication->type) == GSK_SL_DOUBLE)
+ MATRIXMULT(double);
+ else
+ MATRIXMULT(float);
+ gsk_sl_value_free (lvalue);
+ gsk_sl_value_free (rvalue);
+ return result;
+ }
+ else
+ {
+ /* we can multiply componentwise */
+ gsize ln, rn;
+
+ ln = gsk_sl_type_get_n_components (ltype);
+ rn = gsk_sl_type_get_n_components (rtype);
+ if (ln == 1)
+ {
+ gsk_sl_value_componentwise (rvalue, mult_funcs[scalar], gsk_sl_value_get_data (lvalue));
+ gsk_sl_value_free (lvalue);
+ result = rvalue;
+ }
+ else if (rn == 1)
+ {
+ gsk_sl_value_componentwise (lvalue, mult_funcs[scalar], gsk_sl_value_get_data (rvalue));
+ gsk_sl_value_free (rvalue);
+ result = lvalue;
+ }
+ else
+ {
+ guchar *ldata, *rdata;
+ gsize i, stride;
+
+ stride = gsk_sl_scalar_type_get_size (scalar);
+ ldata = gsk_sl_value_get_data (lvalue);
+ rdata = gsk_sl_value_get_data (rvalue);
+ for (i = 0; i < ln; i++)
+ {
+ mult_funcs[scalar] (ldata + i * stride, rdata + i * stride);
+ }
+ gsk_sl_value_free (rvalue);
+ result = lvalue;
+ }
+ }
+
+ return result;
+}
+
+static guint32
+gsk_sl_expression_multiplication_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ const GskSlExpressionMultiplication *multiplication = (const GskSlExpressionMultiplication *) expression;
+ GskSlType *ltype, *rtype;
+ guint32 left_id, right_id, result_id, result_type_id;
+
+ ltype = gsk_sl_expression_get_return_type (multiplication->left);
+ rtype = gsk_sl_expression_get_return_type (multiplication->right);
+
+ left_id = gsk_sl_expression_write_spv (multiplication->left, writer);
+ if (gsk_sl_type_get_scalar_type (ltype) != gsk_sl_type_get_scalar_type (multiplication->type))
+ {
+ GskSlType *new_type = gsk_sl_type_get_matrix (gsk_sl_type_get_scalar_type (multiplication->type),
+ gsk_sl_type_get_length (ltype),
+ gsk_sl_type_get_length (gsk_sl_type_get_index_type
(ltype)));
+ left_id = gsk_spv_writer_add_conversion (writer, left_id, ltype, new_type);
+ }
+ right_id = gsk_sl_expression_write_spv (multiplication->right, writer);
+ if (gsk_sl_type_get_scalar_type (rtype) != gsk_sl_type_get_scalar_type (multiplication->type))
+ {
+ GskSlType *new_type = gsk_sl_type_get_matrix (gsk_sl_type_get_scalar_type (multiplication->type),
+ gsk_sl_type_get_length (rtype),
+ gsk_sl_type_get_length (gsk_sl_type_get_index_type
(rtype)));
+ right_id = gsk_spv_writer_add_conversion (writer, right_id, rtype, new_type);
+ }
+
+ result_type_id = gsk_spv_writer_get_id_for_type (writer, multiplication->type);
+ result_id = gsk_spv_writer_next_id (writer);
+
+ if (gsk_sl_type_is_matrix (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_MATRIX_TIMES_MATRIX,
+ (guint32[4]) { result_type_id,
+ result_id,
+ left_id,
+ right_id });
+
+ return result_id;
+ }
+ else if (gsk_sl_type_is_vector (rtype))
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_VECTOR_TIMES_MATRIX,
+ (guint32[4]) { result_type_id,
+ result_id,
+ right_id,
+ left_id });
+
+ return result_id;
+ }
+ else if (gsk_sl_type_is_scalar (rtype))
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_MATRIX_TIMES_SCALAR,
+ (guint32[4]) { result_type_id,
+ result_id,
+ left_id,
+ right_id });
+
+ return result_id;
+ }
+ }
+ else if (gsk_sl_type_is_vector (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_MATRIX_TIMES_VECTOR,
+ (guint32[4]) { result_type_id,
+ result_id,
+ right_id,
+ left_id });
+
+ return result_id;
+ }
+ else if (gsk_sl_type_is_vector (rtype))
+ {
+ switch (gsk_sl_type_get_scalar_type (multiplication->type))
+ {
+ case GSK_SL_FLOAT:
+ case GSK_SL_DOUBLE:
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_F_MUL,
+ (guint32[4]) { result_type_id,
+ result_id,
+ left_id,
+ right_id });
+ break;
+ case GSK_SL_INT:
+ case GSK_SL_UINT:
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_I_MUL,
+ (guint32[4]) { result_type_id,
+ result_id,
+ left_id,
+ right_id });
+ break;
+ case GSK_SL_VOID:
+ case GSK_SL_BOOL:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return result_id;
+ }
+ else if (gsk_sl_type_is_scalar (rtype))
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_VECTOR_TIMES_SCALAR,
+ (guint32[4]) { result_type_id,
+ result_id,
+ left_id,
+ right_id });
+
+ return result_id;
+ }
+ }
+ else if (gsk_sl_type_is_scalar (ltype))
+ {
+ if (gsk_sl_type_is_matrix (rtype))
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_MATRIX_TIMES_SCALAR,
+ (guint32[4]) { result_type_id,
+ result_id,
+ right_id,
+ left_id });
+
+ return result_id;
+ }
+ else if (gsk_sl_type_is_vector (rtype))
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_VECTOR_TIMES_SCALAR,
+ (guint32[4]) { result_type_id,
+ result_id,
+ right_id,
+ left_id });
+
+ return result_id;
+ }
+ else if (gsk_sl_type_is_scalar (rtype))
+ {
+ switch (gsk_sl_type_get_scalar_type (multiplication->type))
+ {
+ case GSK_SL_FLOAT:
+ case GSK_SL_DOUBLE:
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_F_MUL,
+ (guint32[4]) { result_type_id,
+ result_id,
+ left_id,
+ right_id });
+ break;
+ case GSK_SL_INT:
+ case GSK_SL_UINT:
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_I_MUL,
+ (guint32[4]) { result_type_id,
+ result_id,
+ left_id,
+ right_id });
+ break;
+ case GSK_SL_VOID:
+ case GSK_SL_BOOL:
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return result_id;
+ }
+ }
+
+ g_assert_not_reached ();
+
+ return 0;
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_MULTIPLICATION = {
+ gsk_sl_expression_multiplication_free,
+ gsk_sl_expression_multiplication_print,
+ gsk_sl_expression_multiplication_get_return_type,
+ gsk_sl_expression_multiplication_get_constant,
+ gsk_sl_expression_multiplication_write_spv
+};
+
+/* OPERATION */
typedef enum {
- GSK_SL_OPERATION_MUL,
GSK_SL_OPERATION_DIV,
GSK_SL_OPERATION_MOD,
GSK_SL_OPERATION_ADD,
@@ -222,7 +736,6 @@ gsk_sl_expression_operation_print (const GskSlExpression *expression,
GskSlPrinter *printer)
{
const char *op_str[] = {
- [GSK_SL_OPERATION_MUL] = " * ",
[GSK_SL_OPERATION_DIV] = " / ",
[GSK_SL_OPERATION_MOD] = " % ",
[GSK_SL_OPERATION_ADD] = " + ",
@@ -253,7 +766,6 @@ gsk_sl_expression_operation_print (const GskSlExpression *expression,
static GskSlType *
gsk_sl_expression_arithmetic_type_check (GskSlPreprocessor *stream,
- gboolean multiply,
GskSlType *ltype,
GskSlType *rtype)
{
@@ -280,60 +792,30 @@ gsk_sl_expression_arithmetic_type_check (GskSlPreprocessor *stream,
{
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, TYPE_MISMATCH,
- "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))
{
- 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, TYPE_MISMATCH,
- "Matrix types %s and %s have different size.",
- gsk_sl_type_get_name (ltype), gsk_sl_type_get_name (rtype));
- return NULL;
- }
+ return ltype;
}
- }
- else if (gsk_sl_type_is_vector (rtype))
- {
- if (multiply)
+ else if (gsk_sl_type_can_convert (rtype, ltype))
{
- if (gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
- {
- if (stream)
- gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
- "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)));
+ return rtype;
}
else
{
if (stream)
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
- "Cannot perform arithmetic operation between matrix and vector.");
+ "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 (stream)
+ gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
+ "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,
@@ -352,24 +834,9 @@ gsk_sl_expression_arithmetic_type_check (GskSlPreprocessor *stream,
{
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, TYPE_MISMATCH,
- "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, TYPE_MISMATCH, "Cannot perform arithmetic operation
between vector and matrix.");
- return NULL;
- }
+ if (stream)
+ gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Cannot perform arithmetic operation between
vector and matrix.");
+ return NULL;
}
else if (gsk_sl_type_is_vector (rtype))
{
@@ -568,16 +1035,10 @@ gsk_sl_expression_operation_get_return_type (const GskSlExpression *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:
@@ -2320,9 +2781,8 @@ gsk_sl_expression_parse_multiplicative (GskSlScope *scope,
GskSlPreprocessor *stream)
{
const GskSlToken *token;
- GskSlExpression *expression;
- GskSlExpressionOperation *operation;
- GskSlOperation op;
+ GskSlExpression *expression, *right;
+ enum { MUL, DIV, MOD } op;
expression = gsk_sl_expression_parse_unary (scope, stream);
@@ -2330,35 +2790,72 @@ gsk_sl_expression_parse_multiplicative (GskSlScope *scope,
{
token = gsk_sl_preprocessor_get (stream);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_STAR))
- op = GSK_SL_OPERATION_MUL;
+ op = MUL;
else if (gsk_sl_token_is (token, GSK_SL_TOKEN_SLASH))
- op = GSK_SL_OPERATION_DIV;
+ op = DIV;
else if (gsk_sl_token_is (token, GSK_SL_TOKEN_PERCENT))
- op = GSK_SL_OPERATION_MOD;
+ op = 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 ((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_preprocessor_consume (stream, NULL);
+ right = gsk_sl_expression_parse_unary (scope, stream);
+ if (op == MUL)
{
- gsk_sl_expression_ref (expression);
- gsk_sl_expression_unref ((GskSlExpression *) operation);
+ GskSlType *result_type;
+
+ result_type = gsk_sl_expression_multiplication_get_result_type (stream,
+ gsk_sl_expression_get_return_type
(expression),
+ gsk_sl_expression_get_return_type
(right));
+ if (result_type)
+ {
+ GskSlExpressionMultiplication *multiplication;
+ multiplication = gsk_sl_expression_new (GskSlExpressionMultiplication,
&GSK_SL_EXPRESSION_MULTIPLICATION);
+ multiplication->type = gsk_sl_type_ref (result_type);
+ multiplication->left = expression;
+ multiplication->right = right;
+ expression = (GskSlExpression *) multiplication;
+ }
+ else
+ {
+ gsk_sl_expression_unref ((GskSlExpression *) right);
+ }
+ }
+ else if (op == DIV)
+ {
+ if (gsk_sl_expression_arithmetic_type_check (stream,
+ gsk_sl_expression_get_return_type (expression),
+ gsk_sl_expression_get_return_type (right)))
+ {
+ GskSlExpressionOperation *operation;
+ operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
+ operation->op = GSK_SL_OPERATION_DIV;
+ operation->left = expression;
+ operation->right = right;
+ expression = (GskSlExpression *) operation;
+ }
+ else
+ {
+ gsk_sl_expression_unref ((GskSlExpression *) right);
+ }
}
else
{
- expression = (GskSlExpression *) operation;
+ if (gsk_sl_expression_bitwise_type_check (stream,
+ gsk_sl_expression_get_return_type (expression),
+ gsk_sl_expression_get_return_type (right)))
+ {
+ GskSlExpressionOperation *operation;
+ operation = gsk_sl_expression_new (GskSlExpressionOperation, &GSK_SL_EXPRESSION_OPERATION);
+ operation->op = GSK_SL_OPERATION_MOD;
+ operation->left = expression;
+ operation->right = right;
+ expression = (GskSlExpression *) operation;
+ }
+ else
+ {
+ gsk_sl_expression_unref ((GskSlExpression *) right);
+ }
}
}
@@ -2394,7 +2891,6 @@ gsk_sl_expression_parse_additive (GskSlScope *scope,
gsk_sl_preprocessor_consume (stream, (GskSlExpression *) operation);
operation->right = gsk_sl_expression_parse_additive (scope, stream);
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)))
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]