[gtk+/wip/otte/shader: 12/14] gskslnode: Add support for bitwise operations
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 12/14] gskslnode: Add support for bitwise operations
- Date: Sun, 17 Sep 2017 17:01:44 +0000 (UTC)
commit 630123ae0651c844dc2bb3248608c46ceccce921
Author: Benjamin Otte <otte redhat com>
Date: Sun Sep 17 15:51:42 2017 +0200
gskslnode: Add support for bitwise operations
Includes lots of new API for inspecting types that is necessary to do
compile time checks.
gsk/gskslnode.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++--
gsk/gsksltype.c | 57 ++++++++++++-
gsk/gsksltypeprivate.h | 5 +
3 files changed, 276 insertions(+), 10 deletions(-)
---
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index 927fc9e..b61adfd 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -350,18 +350,89 @@ gsk_sl_node_operation_print (GskSlNode *node,
}
static GskSlType *
-gsk_sl_node_operation_get_return_type (GskSlNode *node)
+gsk_sl_node_bitwise_type_check (GskSlTokenStream *stream,
+ GskSlType *ltype,
+ GskSlType *rtype)
{
- GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
- GskSlType *ltype, *rtype;
+ GskSlScalarType lscalar, rscalar;
- ltype = gsk_sl_node_get_return_type (operation->left);
- rtype = gsk_sl_node_get_return_type (operation->right);
+ lscalar = gsk_sl_type_get_scalar_type (ltype);
+ if (lscalar != GSK_SL_INT && lscalar != GSK_SL_UINT)
+ {
+ if (stream)
+ gsk_sl_token_stream_error (stream, "Left operand is not an integer type.");
+ return NULL;
+ }
+ rscalar = gsk_sl_type_get_scalar_type (ltype);
+ if (rscalar != GSK_SL_INT && rscalar != GSK_SL_UINT)
+ {
+ if (stream)
+ gsk_sl_token_stream_error (stream, "Right operand is not an integer type.");
+ return NULL;
+ }
+ if (!gsk_sl_type_is_scalar (ltype) && !gsk_sl_type_is_vector (ltype))
+ {
+ if (stream)
+ gsk_sl_token_stream_error (stream, "Left operand is neither a scalar nor a vector.");
+ return NULL;
+ }
+ if (!gsk_sl_type_is_scalar (rtype) && !gsk_sl_type_is_vector (rtype))
+ {
+ if (stream)
+ gsk_sl_token_stream_error (stream, "Right operand is neither a scalar nor a vector.");
+ return NULL;
+ }
+ if (gsk_sl_type_is_vector (ltype) && gsk_sl_type_is_vector (rtype) &&
+ gsk_sl_type_get_length (ltype) != gsk_sl_type_get_length (rtype))
+ {
+ if (stream)
+ gsk_sl_token_stream_error (stream, "Vector operands do not have the same length.");
+ return NULL;
+ }
- if (gsk_sl_type_can_convert (ltype, rtype))
- return ltype;
+ rscalar = lscalar == GSK_SL_UINT ? GSK_SL_UINT : rscalar;
+ if (gsk_sl_type_is_scalar (ltype) && gsk_sl_type_is_scalar (rtype))
+ return gsk_sl_type_get_scalar (rscalar);
else
- return rtype;
+ return gsk_sl_type_get_vector (rscalar, gsk_sl_type_get_length (ltype));
+}
+
+static GskSlType *
+gsk_sl_node_operation_get_return_type (GskSlNode *node)
+{
+ GskSlNodeOperation *operation = (GskSlNodeOperation *) node;
+
+ switch (operation->op)
+ {
+ case GSK_SL_OPERATION_MUL:
+ case GSK_SL_OPERATION_DIV:
+ case GSK_SL_OPERATION_MOD:
+ case GSK_SL_OPERATION_ADD:
+ case GSK_SL_OPERATION_SUB:
+ case GSK_SL_OPERATION_LSHIFT:
+ case GSK_SL_OPERATION_RSHIFT:
+ case GSK_SL_OPERATION_LESS:
+ case GSK_SL_OPERATION_GREATER:
+ case GSK_SL_OPERATION_LESS_EQUAL:
+ case GSK_SL_OPERATION_GREATER_EQUAL:
+ case GSK_SL_OPERATION_EQUAL:
+ case GSK_SL_OPERATION_NOT_EQUAL:
+ g_assert_not_reached ();
+ return NULL;
+ case GSK_SL_OPERATION_AND:
+ case GSK_SL_OPERATION_XOR:
+ case GSK_SL_OPERATION_OR:
+ return gsk_sl_node_bitwise_type_check (NULL,
+ gsk_sl_node_get_return_type (operation->left),
+ gsk_sl_node_get_return_type (operation->right));
+ case GSK_SL_OPERATION_LOGICAL_AND:
+ case GSK_SL_OPERATION_LOGICAL_XOR:
+ case GSK_SL_OPERATION_LOGICAL_OR:
+ return gsk_sl_type_get_scalar (GSK_SL_BOOL);
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
}
static gboolean
@@ -709,11 +780,146 @@ gsk_sl_node_parse_primary_expression (GskSlNodeProgram *program,
}
static GskSlNode *
+gsk_sl_node_parse_equality_expression (GskSlNodeProgram *program,
+ GskSlScope *scope,
+ GskSlTokenStream *stream)
+{
+ return gsk_sl_node_parse_primary_expression (program, scope, stream);
+}
+
+static GskSlNode *
+gsk_sl_node_parse_and_expression (GskSlNodeProgram *program,
+ GskSlScope *scope,
+ GskSlTokenStream *stream)
+{
+ const GskSlToken *token;
+ GskSlNode *node;
+ GskSlNodeOperation *operation;
+
+ node = gsk_sl_node_parse_equality_expression (program, scope, stream);
+ if (node == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_token_stream_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_token_stream_consume (stream, (GskSlNode *) operation);
+ operation->right = gsk_sl_node_parse_equality_expression (program, scope, stream);
+ if (operation->right == NULL)
+ {
+ gsk_sl_node_ref (node);
+ gsk_sl_node_unref ((GskSlNode *) operation);
+ }
+ else if (!gsk_sl_node_bitwise_type_check (stream,
+ gsk_sl_node_get_return_type (operation->left),
+ gsk_sl_node_get_return_type (operation->right)))
+ {
+ gsk_sl_node_ref (node);
+ gsk_sl_node_unref ((GskSlNode *) operation);
+ }
+ else
+ {
+ node = (GskSlNode *) operation;
+ }
+ }
+
+ return node;
+}
+
+static GskSlNode *
+gsk_sl_node_parse_xor_expression (GskSlNodeProgram *program,
+ GskSlScope *scope,
+ GskSlTokenStream *stream)
+{
+ const GskSlToken *token;
+ GskSlNode *node;
+ GskSlNodeOperation *operation;
+
+ node = gsk_sl_node_parse_and_expression (program, scope, stream);
+ if (node == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_token_stream_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_token_stream_consume (stream, (GskSlNode *) operation);
+ operation->right = gsk_sl_node_parse_and_expression (program, scope, stream);
+ if (operation->right == NULL)
+ {
+ gsk_sl_node_ref (node);
+ gsk_sl_node_unref ((GskSlNode *) operation);
+ }
+ else if (!gsk_sl_node_bitwise_type_check (stream,
+ gsk_sl_node_get_return_type (operation->left),
+ gsk_sl_node_get_return_type (operation->right)))
+ {
+ gsk_sl_node_ref (node);
+ gsk_sl_node_unref ((GskSlNode *) operation);
+ }
+ else
+ {
+ node = (GskSlNode *) operation;
+ }
+ }
+
+ return node;
+}
+
+static GskSlNode *
gsk_sl_node_parse_or_expression (GskSlNodeProgram *program,
GskSlScope *scope,
GskSlTokenStream *stream)
{
- return gsk_sl_node_parse_primary_expression (program, scope, stream);
+ const GskSlToken *token;
+ GskSlNode *node;
+ GskSlNodeOperation *operation;
+
+ node = gsk_sl_node_parse_xor_expression (program, scope, stream);
+ if (node == NULL)
+ return NULL;
+
+ while (TRUE)
+ {
+ token = gsk_sl_token_stream_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_token_stream_consume (stream, (GskSlNode *) operation);
+ operation->right = gsk_sl_node_parse_xor_expression (program, scope, stream);
+ if (operation->right == NULL)
+ {
+ gsk_sl_node_ref (node);
+ gsk_sl_node_unref ((GskSlNode *) operation);
+ }
+ else if (!gsk_sl_node_bitwise_type_check (stream,
+ gsk_sl_node_get_return_type (operation->left),
+ gsk_sl_node_get_return_type (operation->right)))
+ {
+ gsk_sl_node_ref (node);
+ gsk_sl_node_unref ((GskSlNode *) operation);
+ }
+ else
+ {
+ node = (GskSlNode *) operation;
+ }
+ }
+
+ return node;
}
static GskSlNode *
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index 5bfe366..da6f4f9 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -42,6 +42,7 @@ struct _GskSlTypeClass {
void (* print) (GskSlType *type,
GString *string);
GskSlScalarType (* get_scalar_type) (GskSlType *type);
+ guint (* get_length) (GskSlType *type);
gboolean (* can_convert) (GskSlType *target,
GskSlType *source);
};
@@ -125,6 +126,12 @@ gsk_sl_type_scalar_get_scalar_type (GskSlType *type)
return scalar->scalar;
}
+static guint
+gsk_sl_type_scalar_get_length (GskSlType *type)
+{
+ return 0;
+}
+
static gboolean
gsk_sl_type_scalar_can_convert (GskSlType *target,
GskSlType *source)
@@ -142,6 +149,7 @@ static const GskSlTypeClass GSK_SL_TYPE_SCALAR = {
gsk_sl_type_scalar_free,
gsk_sl_type_scalar_print,
gsk_sl_type_scalar_get_scalar_type,
+ gsk_sl_type_scalar_get_length,
gsk_sl_type_scalar_can_convert
};
@@ -202,6 +210,14 @@ gsk_sl_type_vector_get_scalar_type (GskSlType *type)
return vector->scalar;
}
+static guint
+gsk_sl_type_vector_get_length (GskSlType *type)
+{
+ GskSlTypeVector *vector = (GskSlTypeVector *) type;
+
+ return vector->length;
+}
+
static gboolean
gsk_sl_type_vector_can_convert (GskSlType *target,
GskSlType *source)
@@ -219,6 +235,7 @@ static const GskSlTypeClass GSK_SL_TYPE_VECTOR = {
gsk_sl_type_vector_free,
gsk_sl_type_vector_print,
gsk_sl_type_vector_get_scalar_type,
+ gsk_sl_type_vector_get_length,
gsk_sl_type_vector_can_convert
};
@@ -262,6 +279,14 @@ gsk_sl_type_matrix_get_scalar_type (GskSlType *type)
return matrix->scalar;
}
+static guint
+gsk_sl_type_matrix_get_length (GskSlType *type)
+{
+ GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
+
+ return matrix->columns;
+}
+
static gboolean
gsk_sl_type_matrix_can_convert (GskSlType *target,
GskSlType *source)
@@ -279,6 +304,7 @@ static const GskSlTypeClass GSK_SL_TYPE_MATRIX = {
gsk_sl_type_matrix_free,
gsk_sl_type_matrix_print,
gsk_sl_type_matrix_get_scalar_type,
+ gsk_sl_type_matrix_get_length,
gsk_sl_type_matrix_can_convert
};
@@ -578,9 +604,38 @@ gsk_sl_type_to_string (const GskSlType *type)
}
gboolean
+gsk_sl_type_is_scalar (const GskSlType *type)
+{
+ return type->class == &GSK_SL_TYPE_SCALAR;
+}
+
+gboolean
+gsk_sl_type_is_vector (const GskSlType *type)
+{
+ return type->class == &GSK_SL_TYPE_VECTOR;
+}
+
+gboolean
+gsk_sl_type_is_matrix (const GskSlType *type)
+{
+ return type->class == &GSK_SL_TYPE_MATRIX;
+}
+
+GskSlScalarType
+gsk_sl_type_get_scalar_type (const GskSlType *type)
+{
+ return type->class->get_scalar_type (type);
+}
+
+GskSlScalarType
+gsk_sl_type_get_length (const GskSlType *type)
+{
+ return type->class->get_length (type);
+}
+
+gboolean
gsk_sl_type_can_convert (const GskSlType *target,
const GskSlType *source)
{
return target->class->can_convert (target, source);
}
-
diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h
index 3fc9160..6f3514c 100644
--- a/gsk/gsksltypeprivate.h
+++ b/gsk/gsksltypeprivate.h
@@ -51,6 +51,11 @@ void gsk_sl_type_print (const GskSlType
GString *string);
char * gsk_sl_type_to_string (const GskSlType *type);
+gboolean gsk_sl_type_is_scalar (const GskSlType *type);
+gboolean gsk_sl_type_is_vector (const GskSlType *type);
+gboolean gsk_sl_type_is_matrix (const GskSlType *type);
+GskSlScalarType gsk_sl_type_get_scalar_type (const GskSlType *type);
+guint gsk_sl_type_get_length (const GskSlType *type);
gboolean gsk_sl_type_can_convert (const GskSlType *target,
const GskSlType *source);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]