[gtk+/wip/otte/shader: 24/127] gsksl: Turn functions into functions
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 24/127] gsksl: Turn functions into functions
- Date: Thu, 12 Oct 2017 23:58:26 +0000 (UTC)
commit 8d7055fb6e5038d0df7b97e39a2ac32bfb103823
Author: Benjamin Otte <otte redhat com>
Date: Sun Sep 24 23:13:54 2017 +0200
gsksl: Turn functions into functions
Don't use a GskSlNode subclass to handle declared functions but make
them a GskSlFunction subclass.
gsk/gskslfunction.c | 287 +++++++++++++++++++++--
gsk/gskslfunctionprivate.h | 47 +++--
gsk/gskslnode.c | 552 +++++++++++++++++---------------------------
gsk/gskslnodeprivate.h | 2 +-
gsk/gskslprogram.c | 63 ++++--
gsk/gskslscope.c | 15 ++-
gsk/gskslscopeprivate.h | 5 +-
7 files changed, 581 insertions(+), 390 deletions(-)
---
diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c
index bbff985..c9e2ac5 100644
--- a/gsk/gskslfunction.c
+++ b/gsk/gskslfunction.c
@@ -20,7 +20,12 @@
#include "gskslfunctionprivate.h"
+#include "gskslnodeprivate.h"
+#include "gskslpreprocessorprivate.h"
+#include "gskslscopeprivate.h"
+#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
+#include "gskspvwriterprivate.h"
static GskSlFunction *
gsk_sl_function_alloc (const GskSlFunctionClass *klass,
@@ -58,22 +63,27 @@ gsk_sl_function_constructor_free (GskSlFunction *function)
}
static GskSlType *
-gsk_sl_function_constructor_get_return_type (GskSlFunction *function)
+gsk_sl_function_constructor_get_return_type (const GskSlFunction *function)
{
- GskSlFunctionConstructor *constructor = (GskSlFunctionConstructor *) function;
+ const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
return constructor->type;
}
static void
-gsk_sl_function_constructor_print_name (GskSlFunction *function,
- GString *string)
+gsk_sl_function_constructor_print_name (const GskSlFunction *function,
+ GString *string)
{
- GskSlFunctionConstructor *constructor = (GskSlFunctionConstructor *) function;
+ const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
g_string_append (string, gsk_sl_type_get_name (constructor->type));
}
+static void
+gsk_sl_function_constructor_print (const GskSlFunction *function,
+ GString *string)
+{
+}
static guint
gsk_sl_function_builtin_get_args_by_type (const GskSlType *type)
@@ -89,12 +99,12 @@ gsk_sl_function_builtin_get_args_by_type (const GskSlType *type)
}
static gboolean
-gsk_sl_function_constructor_matches (GskSlFunction *function,
- GskSlType **arguments,
- gsize n_arguments,
- GError **error)
+gsk_sl_function_constructor_matches (const GskSlFunction *function,
+ GskSlType **arguments,
+ gsize n_arguments,
+ GError **error)
{
- GskSlFunctionConstructor *constructor = (GskSlFunctionConstructor *) function;
+ const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
guint needed, provided;
gsize i;
@@ -127,11 +137,161 @@ gsk_sl_function_constructor_matches (GskSlFunction *function,
return TRUE;
}
+static guint32
+gsk_sl_function_constructor_write_spv (const GskSlFunction *function,
+ GskSpvWriter *writer)
+{
+ return 0;
+}
+
static const GskSlFunctionClass GSK_SL_FUNCTION_CONSTRUCTOR = {
gsk_sl_function_constructor_free,
gsk_sl_function_constructor_get_return_type,
gsk_sl_function_constructor_print_name,
+ gsk_sl_function_constructor_print,
gsk_sl_function_constructor_matches,
+ gsk_sl_function_constructor_write_spv,
+};
+
+/* DECLARED */
+
+typedef struct _GskSlFunctionDeclared GskSlFunctionDeclared;
+
+struct _GskSlFunctionDeclared {
+ GskSlFunction parent;
+
+ GskSlScope *scope;
+ GskSlType *return_type;
+ char *name;
+ GSList *statements;
+};
+
+static void
+gsk_sl_function_declared_free (GskSlFunction *function)
+{
+ GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
+
+ if (declared->scope)
+ gsk_sl_scope_unref (declared->scope);
+ if (declared->return_type)
+ gsk_sl_type_unref (declared->return_type);
+ g_free (declared->name);
+ g_slist_free_full (declared->statements, (GDestroyNotify) gsk_sl_node_unref);
+
+ g_slice_free (GskSlFunctionDeclared, declared);
+}
+
+static GskSlType *
+gsk_sl_function_declared_get_return_type (const GskSlFunction *function)
+{
+ const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
+
+ return declared->return_type;
+}
+
+static void
+gsk_sl_function_declared_print_name (const GskSlFunction *function,
+ GString *string)
+{
+ const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
+
+ g_string_append (string, declared->name);
+}
+
+static void
+gsk_sl_function_declared_print (const GskSlFunction *function,
+ GString *string)
+{
+ const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
+ GSList *l;
+
+ g_string_append (string, gsk_sl_type_get_name (declared->return_type));
+ g_string_append (string, "\n");
+
+ g_string_append (string, declared->name);
+ g_string_append (string, " (");
+ g_string_append (string, ")\n");
+
+ g_string_append (string, "{\n");
+ for (l = declared->statements; l; l = l->next)
+ {
+ g_string_append (string, " ");
+ gsk_sl_node_print (l->data, string);
+ g_string_append (string, ";\n");
+ }
+ g_string_append (string, "}\n");
+}
+
+static gboolean
+gsk_sl_function_declared_matches (const GskSlFunction *function,
+ GskSlType **arguments,
+ gsize n_arguments,
+ GError **error)
+{
+ if (n_arguments > 0)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Function only takes %u arguments.", 0);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static guint32
+gsk_sl_function_declared_write_spv (const GskSlFunction *function,
+ GskSpvWriter *writer)
+{
+ GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
+ guint32 return_type_id, function_type_id, function_id, label_id;
+ GSList *l;
+
+ /* declare type of function */
+ return_type_id = gsk_spv_writer_get_id_for_type (writer, declared->return_type);
+ function_type_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_DECLARE,
+ 3, GSK_SPV_OP_TYPE_FUNCTION,
+ (guint32[2]) { function_type_id,
+ return_type_id });
+
+ /* add debug info */
+ /* FIXME */
+
+ /* add function body */
+ function_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5, GSK_SPV_OP_FUNCTION,
+ (guint32[4]) { return_type_id,
+ function_id,
+ 0,
+ function_type_id });
+ label_id = gsk_spv_writer_next_id (writer);
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 2, GSK_SPV_OP_LABEL,
+ (guint32[1]) { label_id });
+
+ for (l = declared->statements; l; l = l->next)
+ {
+ gsk_sl_node_write_spv (l->data, writer);
+ }
+
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 1, GSK_SPV_OP_FUNCTION_END,
+ NULL);
+
+ return function_id;
+}
+
+static const GskSlFunctionClass GSK_SL_FUNCTION_DECLARED = {
+ gsk_sl_function_declared_free,
+ gsk_sl_function_declared_get_return_type,
+ gsk_sl_function_declared_print_name,
+ gsk_sl_function_declared_print,
+ gsk_sl_function_declared_matches,
+ gsk_sl_function_declared_write_spv,
};
/* API */
@@ -149,6 +309,85 @@ gsk_sl_function_new_constructor (GskSlType *type)
}
GskSlFunction *
+gsk_sl_function_new_parse (GskSlScope *scope,
+ GskSlPreprocessor *preproc,
+ GskSlType *return_type,
+ const char *name)
+{
+ GskSlFunctionDeclared *function;
+ const GskSlToken *token;
+ gboolean success = TRUE;
+
+ function = gsk_sl_function_new (GskSlFunctionDeclared, &GSK_SL_FUNCTION_DECLARED);
+ function->return_type = gsk_sl_type_ref (return_type);
+ function->name = g_strdup (name);
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
+ {
+ gsk_sl_preprocessor_error (preproc, "Expected an openening \"(\"");
+ gsk_sl_function_unref ((GskSlFunction *) function);
+ return NULL;
+ }
+ gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
+ {
+ gsk_sl_preprocessor_error (preproc, "Expected a closing \")\"");
+ gsk_sl_function_unref ((GskSlFunction *) function);
+ return NULL;
+ }
+ gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
+ {
+ gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
+ return (GskSlFunction *) function;
+ }
+
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
+ {
+ gsk_sl_preprocessor_error (preproc, "Expected an opening \"{\"");
+ gsk_sl_function_unref ((GskSlFunction *) function);
+ return NULL;
+ }
+ gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
+
+ function->scope = gsk_sl_scope_new (scope, function->return_type);
+
+ for (token = gsk_sl_preprocessor_get (preproc);
+ !gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE) && !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
+ token = gsk_sl_preprocessor_get (preproc))
+ {
+ GskSlNode *statement;
+
+ statement = gsk_sl_node_parse_statement (function->scope, preproc);
+ if (statement)
+ function->statements = g_slist_append (function->statements, statement);
+ else
+ success = FALSE;
+ }
+
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE))
+ {
+ gsk_sl_preprocessor_error (preproc, "Missing closing \"}\" at end.");
+ gsk_sl_function_unref ((GskSlFunction *) function);
+ return NULL;
+ }
+ gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function);
+
+ if (!success)
+ {
+ gsk_sl_function_unref ((GskSlFunction *) function);
+ return NULL;
+ }
+
+ return (GskSlFunction *) function;
+}
+
+GskSlFunction *
gsk_sl_function_ref (GskSlFunction *function)
{
g_return_val_if_fail (function != NULL, NULL);
@@ -172,24 +411,38 @@ gsk_sl_function_unref (GskSlFunction *function)
}
GskSlType *
-gsk_sl_function_get_return_type (GskSlFunction *function)
+gsk_sl_function_get_return_type (const GskSlFunction *function)
{
return function->class->get_return_type (function);
}
void
-gsk_sl_function_print_name (GskSlFunction *function,
- GString *string)
+gsk_sl_function_print_name (const GskSlFunction *function,
+ GString *string)
{
function->class->print_name (function, string);
}
+void
+gsk_sl_function_print (const GskSlFunction *function,
+ GString *string)
+{
+ function->class->print (function, string);
+}
+
gboolean
-gsk_sl_function_matches (GskSlFunction *function,
- GskSlType **arguments,
- gsize n_arguments,
- GError **error)
+gsk_sl_function_matches (const GskSlFunction *function,
+ GskSlType **arguments,
+ gsize n_arguments,
+ GError **error)
{
return function->class->matches (function, arguments, n_arguments, error);
}
+guint32
+gsk_sl_function_write_spv (const GskSlFunction *function,
+ GskSpvWriter *writer)
+{
+ return function->class->write_spv (function, writer);
+}
+
diff --git a/gsk/gskslfunctionprivate.h b/gsk/gskslfunctionprivate.h
index 7005fd9..99967cb 100644
--- a/gsk/gskslfunctionprivate.h
+++ b/gsk/gskslfunctionprivate.h
@@ -37,27 +37,40 @@ struct _GskSlFunction
struct _GskSlFunctionClass {
void (* free) (GskSlFunction *function);
- GskSlType * (* get_return_type) (GskSlFunction *function);
- void (* print_name) (GskSlFunction *function,
- GString *string);
- gboolean (* matches) (GskSlFunction *function,
- GskSlType **arguments,
- gsize n_arguments,
- GError **error);
+ GskSlType * (* get_return_type) (const GskSlFunction *function);
+ void (* print_name) (const GskSlFunction *function,
+ GString *string);
+ void (* print) (const GskSlFunction *function,
+ GString *string);
+ gboolean (* matches) (const GskSlFunction *function,
+ GskSlType **arguments,
+ gsize n_arguments,
+ GError **error);
+ guint32 (* write_spv) (const GskSlFunction *function,
+ GskSpvWriter *writer);
};
-GskSlFunction * gsk_sl_function_new_constructor (GskSlType *type);
+GskSlFunction * gsk_sl_function_new_constructor (GskSlType *type);
+GskSlFunction * gsk_sl_function_new_parse (GskSlScope *scope,
+ GskSlPreprocessor *stream,
+ GskSlType *return_type,
+ const char *name);
-GskSlFunction * gsk_sl_function_ref (GskSlFunction *function);
-void gsk_sl_function_unref (GskSlFunction *function);
+GskSlFunction * gsk_sl_function_ref (GskSlFunction *function);
+void gsk_sl_function_unref (GskSlFunction *function);
-void gsk_sl_function_print_name (GskSlFunction *function,
- GString *string);
-GskSlType * gsk_sl_function_get_return_type (GskSlFunction *function);
-gboolean gsk_sl_function_matches (GskSlFunction *function,
- GskSlType **arguments,
- gsize n_arguments,
- GError **error);
+void gsk_sl_function_print (const GskSlFunction *function,
+ GString *string);
+
+void gsk_sl_function_print_name (const GskSlFunction *function,
+ GString *string);
+GskSlType * gsk_sl_function_get_return_type (const GskSlFunction *function);
+gboolean gsk_sl_function_matches (const GskSlFunction *function,
+ GskSlType **arguments,
+ gsize n_arguments,
+ GError **error);
+guint32 gsk_sl_function_write_spv (const GskSlFunction *function,
+ GskSpvWriter *writer);
G_END_DECLS
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index 6e5fa82..62afbbb 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -47,109 +47,42 @@ gsk_sl_node_alloc (const GskSlNodeClass *klass,
}
#define gsk_sl_node_new(_name, _klass) ((_name *) gsk_sl_node_alloc ((_klass), sizeof (_name)))
-/* FUNCTION */
+/* EMPTY */
-typedef struct _GskSlNodeFunction GskSlNodeFunction;
+/* FIXME: This exists only so we dont return NULL from empty statements (ie just a semicolon)
+ */
-struct _GskSlNodeFunction {
- GskSlNode parent;
+typedef struct _GskSlNodeEmpty GskSlNodeEmpty;
- GskSlScope *scope;
- GskSlType *return_type;
- char *name;
- GSList *statements;
+struct _GskSlNodeEmpty {
+ GskSlNode parent;
};
static void
-gsk_sl_node_function_free (GskSlNode *node)
+gsk_sl_node_empty_free (GskSlNode *node)
{
- GskSlNodeFunction *function = (GskSlNodeFunction *) node;
+ GskSlNodeEmpty *empty = (GskSlNodeEmpty *) node;
- if (function->scope)
- gsk_sl_scope_unref (function->scope);
- if (function->return_type)
- gsk_sl_type_unref (function->return_type);
- g_free (function->name);
- g_slist_free_full (function->statements, (GDestroyNotify) gsk_sl_node_unref);
-
- g_slice_free (GskSlNodeFunction, function);
+ g_slice_free (GskSlNodeEmpty, empty);
}
static void
-gsk_sl_node_function_print (GskSlNode *node,
- GString *string)
+gsk_sl_node_empty_print (GskSlNode *node,
+ GString *string)
{
- GskSlNodeFunction *function = (GskSlNodeFunction *) node;
- GSList *l;
-
- g_string_append (string, gsk_sl_type_get_name (function->return_type));
- g_string_append (string, "\n");
-
- g_string_append (string, function->name);
- g_string_append (string, " (");
- g_string_append (string, ")\n");
-
- g_string_append (string, "{\n");
- for (l = function->statements; l; l = l->next)
- {
- g_string_append (string, " ");
- gsk_sl_node_print (l->data, string);
- g_string_append (string, ";\n");
- }
- g_string_append (string, "}\n");
}
static guint32
-gsk_sl_node_function_write_spv (const GskSlNode *node,
- GskSpvWriter *writer)
+gsk_sl_node_empty_write_spv (const GskSlNode *node,
+ GskSpvWriter *writer)
{
- GskSlNodeFunction *function = (GskSlNodeFunction *) node;
- guint32 return_type_id, function_type_id, function_id, label_id;
- GSList *l;
-
- /* declare type of function */
- return_type_id = gsk_spv_writer_get_id_for_type (writer, function->return_type);
- function_type_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_DECLARE,
- 3, GSK_SPV_OP_TYPE_FUNCTION,
- (guint32[2]) { function_type_id,
- return_type_id });
-
- /* add debug info */
- /* FIXME */
-
- /* add function body */
- function_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_CODE,
- 5, GSK_SPV_OP_FUNCTION,
- (guint32[4]) { return_type_id,
- function_id,
- 0,
- function_type_id });
- label_id = gsk_spv_writer_next_id (writer);
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_CODE,
- 2, GSK_SPV_OP_LABEL,
- (guint32[4]) { label_id });
-
- for (l = function->statements; l; l = l->next)
- {
- gsk_sl_node_write_spv (l->data, writer);
- }
-
- gsk_spv_writer_add (writer,
- GSK_SPV_WRITER_SECTION_CODE,
- 1, GSK_SPV_OP_FUNCTION_END,
- NULL);
- return function_id;
+ return 0;
}
-static const GskSlNodeClass GSK_SL_NODE_FUNCTION = {
- gsk_sl_node_function_free,
- gsk_sl_node_function_print,
- gsk_sl_node_function_write_spv
+static const GskSlNodeClass GSK_SL_NODE_EMPTY = {
+ gsk_sl_node_empty_free,
+ gsk_sl_node_empty_print,
+ gsk_sl_node_empty_write_spv
};
/* DECLARATION */
@@ -312,52 +245,6 @@ static const GskSlNodeClass GSK_SL_NODE_EXPRESSION = {
/* API */
-static GskSlNodeFunction *
-gsk_sl_node_parse_function_prototype (GskSlScope *scope,
- GskSlPreprocessor *stream)
-{
- GskSlType *type;
- GskSlNodeFunction *function;
- const GskSlToken *token;
-
- type = gsk_sl_type_new_parse (stream);
- if (type == NULL)
- return NULL;
-
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
- {
- gsk_sl_preprocessor_error (stream, "Expected a function name");
- gsk_sl_type_unref (type);
- return NULL;
- }
-
- function = gsk_sl_node_new (GskSlNodeFunction, &GSK_SL_NODE_FUNCTION);
- function->return_type = type;
- function->name = g_strdup (token->str);
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
-
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
- {
- gsk_sl_preprocessor_error (stream, "Expected an openening \"(\"");
- gsk_sl_node_unref ((GskSlNode *) function);
- return NULL;
- }
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
-
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
- {
- gsk_sl_preprocessor_error (stream, "Expected a closing \")\"");
- gsk_sl_node_unref ((GskSlNode *) function);
- return NULL;
- }
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
-
- return function;
-}
-
static GskSlNode *
gsk_sl_node_parse_declaration (GskSlScope *scope,
GskSlPreprocessor *stream,
@@ -391,239 +278,228 @@ gsk_sl_node_parse_declaration (GskSlScope *scope,
}
GskSlNode *
-gsk_sl_node_parse_function_definition (GskSlScope *scope,
- GskSlPreprocessor *stream)
+gsk_sl_node_parse_statement (GskSlScope *scope,
+ GskSlPreprocessor *preproc)
{
- GskSlNodeFunction *function;
const GskSlToken *token;
- gboolean result = TRUE;
-
- function = gsk_sl_node_parse_function_prototype (scope, stream);
- if (function == NULL)
- return FALSE;
+ GskSlNode *node;
- token = gsk_sl_preprocessor_get (stream);
- if (gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
- {
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
- return (GskSlNode *) function;
- }
+ token = gsk_sl_preprocessor_get (preproc);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
- {
- gsk_sl_preprocessor_error (stream, "Expected an opening \"{\"");
- gsk_sl_node_unref ((GskSlNode *) function);
- return FALSE;
- }
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
+ switch ((guint) token->type)
+ {
+ case GSK_SL_TOKEN_SEMICOLON:
+ node = (GskSlNode *) gsk_sl_node_new (GskSlNodeEmpty, &GSK_SL_NODE_EMPTY);
+ break;
- function->scope = gsk_sl_scope_new (scope);
+ case GSK_SL_TOKEN_EOF:
+ gsk_sl_preprocessor_error (preproc, "Unexpected end of document");
+ return NULL;
- while (TRUE)
- {
- token = gsk_sl_preprocessor_get (stream);
- switch ((guint) token->type)
+ case GSK_SL_TOKEN_CONST:
+ case GSK_SL_TOKEN_IN:
+ case GSK_SL_TOKEN_OUT:
+ case GSK_SL_TOKEN_INOUT:
+ case GSK_SL_TOKEN_INVARIANT:
+ case GSK_SL_TOKEN_COHERENT:
+ case GSK_SL_TOKEN_VOLATILE:
+ case GSK_SL_TOKEN_RESTRICT:
+ case GSK_SL_TOKEN_READONLY:
+ case GSK_SL_TOKEN_WRITEONLY:
+ 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:
{
- case GSK_SL_TOKEN_SEMICOLON:
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
- break;
-
- case GSK_SL_TOKEN_EOF:
- gsk_sl_preprocessor_error (stream, "Unexpected end of function, expected \"}\"");
- goto out;
-
- case GSK_SL_TOKEN_RIGHT_BRACE:
- goto out;
-
- case GSK_SL_TOKEN_CONST:
- case GSK_SL_TOKEN_IN:
- case GSK_SL_TOKEN_OUT:
- case GSK_SL_TOKEN_INOUT:
- case GSK_SL_TOKEN_INVARIANT:
- case GSK_SL_TOKEN_COHERENT:
- case GSK_SL_TOKEN_VOLATILE:
- case GSK_SL_TOKEN_RESTRICT:
- case GSK_SL_TOKEN_READONLY:
- case GSK_SL_TOKEN_WRITEONLY:
- 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;
- GskSlPointerTypeFlags flags;
- gboolean success;
- GskSlNode *node = NULL;
-
- success = gsk_sl_type_qualifier_parse (stream,
- GSK_SL_POINTER_TYPE_PARAMETER_QUALIFIER
- | GSK_SL_POINTER_TYPE_MEMORY_QUALIFIER,
- &flags);
-
- type = gsk_sl_type_new_parse (stream);
- if (type == NULL)
+ GskSlType *type;
+ GskSlPointerTypeFlags flags;
+ gboolean success;
+
+ success = gsk_sl_type_qualifier_parse (preproc,
+ GSK_SL_POINTER_TYPE_PARAMETER_QUALIFIER
+ | GSK_SL_POINTER_TYPE_MEMORY_QUALIFIER,
+ &flags);
+
+ type = gsk_sl_type_new_parse (preproc);
+ if (type == NULL)
+ {
+ node = NULL;
break;
+ }
- token = gsk_sl_preprocessor_get (stream);
-
- if (token->type == GSK_SL_TOKEN_LEFT_BRACE)
- {
- 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
- {
- GskSlPointerType *pointer_type;
-
- pointer_type = gsk_sl_pointer_type_new (type, flags | GSK_SL_POINTER_TYPE_LOCAL);
- node = gsk_sl_node_parse_declaration (function->scope, stream, pointer_type);
- gsk_sl_pointer_type_unref (pointer_type);
- }
+ token = gsk_sl_preprocessor_get (preproc);
- gsk_sl_type_unref (type);
-
- if (!success)
- {
- gsk_sl_node_unref (node);
- }
- else if (node)
- {
- function->statements = g_slist_append (function->statements, node);
- }
- }
- break;
-
- case GSK_SL_TOKEN_RETURN:
- {
- GskSlNodeReturn *return_node;
-
- return_node = gsk_sl_node_new (GskSlNodeReturn, &GSK_SL_NODE_RETURN);
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) return_node);
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
- {
- return_node->value = gsk_sl_expression_parse (function->scope, stream);
- if (return_node->value == NULL)
- {
- gsk_sl_node_unref ((GskSlNode *) return_node);
- break;
- }
- if (function->return_type == NULL)
- {
- gsk_sl_preprocessor_error (stream, "Cannot return a value from a void function.");
- gsk_sl_node_unref ((GskSlNode *) return_node);
- break;
- }
- 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_expression_get_return_type
(return_node->value)),
- gsk_sl_type_get_name (function->return_type));
- gsk_sl_node_unref ((GskSlNode *) return_node);
- break;
- }
+ if (token->type == GSK_SL_TOKEN_LEFT_PAREN)
+ {
+ GskSlExpression *expression = gsk_sl_expression_parse_constructor_call (scope, preproc, type);
+
+ if (expression)
+ {
+ GskSlNodeExpression *node_expression;
+
+ node_expression = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
+ node_expression->expression = expression;
+ node = (GskSlNode *) node_expression;
}
else
{
- if (function->return_type != NULL)
- {
- gsk_sl_preprocessor_error (stream, "Return statement does not return a value.");
- gsk_sl_node_unref ((GskSlNode *) return_node);
- break;
- }
+ node = NULL;
}
- function->statements = g_slist_append (function->statements, return_node);
}
- break;
+ else
+ {
+ GskSlPointerType *pointer_type;
+
+ pointer_type = gsk_sl_pointer_type_new (type, flags | GSK_SL_POINTER_TYPE_LOCAL);
+ node = gsk_sl_node_parse_declaration (scope, preproc, pointer_type);
+ gsk_sl_pointer_type_unref (pointer_type);
+ }
+
+ gsk_sl_type_unref (type);
+
+ if (!success)
+ {
+ gsk_sl_node_unref (node);
+ node = NULL;
+ }
+ }
+ break;
- default:
- {
- GskSlExpression * expression = gsk_sl_expression_parse (function->scope, stream);
+ case GSK_SL_TOKEN_RETURN:
+ {
+ GskSlNodeReturn *return_node;
+ GskSlType *return_type;
- if (expression)
- {
- GskSlNodeExpression *node;
-
- node = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
- node->expression = expression;
+ return_node = gsk_sl_node_new (GskSlNodeReturn, &GSK_SL_NODE_RETURN);
+ gsk_sl_preprocessor_consume (preproc, (GskSlNode *) return_node);
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
+ {
+ return_node->value = gsk_sl_expression_parse (scope, preproc);
- function->statements = g_slist_append (function->statements, node);
- }
- else
- {
- result = FALSE;
+ if (return_node->value == NULL)
+ {
+ gsk_sl_node_unref ((GskSlNode *) return_node);
+ node = NULL;
+ break;
+ }
+ }
+
+ return_type = gsk_sl_scope_get_return_type (scope);
+ node = (GskSlNode *) return_node;
+
+ if (return_type == NULL)
+ {
+ gsk_sl_preprocessor_error (preproc, "Cannot return from here.");
+ gsk_sl_node_unref (node);
+ node = NULL;
+ }
+ else if (return_node->value == NULL)
+ {
+ if (!gsk_sl_type_equal (return_type, gsk_sl_type_get_scalar (GSK_SL_VOID)))
+ {
+ gsk_sl_preprocessor_error (preproc, "Functions expectes a return value of type %s",
gsk_sl_type_get_name (return_type));
+ gsk_sl_node_unref (node);
+ node = NULL;
+ }
+ }
+ else
+ {
+ if (gsk_sl_type_equal (return_type, gsk_sl_type_get_scalar (GSK_SL_VOID)))
+ {
+ gsk_sl_preprocessor_error (preproc, "Cannot return a value from a void function.");
+ gsk_sl_node_unref (node);
+ node = NULL;
+ }
+ else if (!gsk_sl_type_can_convert (return_type, gsk_sl_expression_get_return_type
(return_node->value)))
+ {
+ gsk_sl_preprocessor_error (preproc,
+ "Cannot convert type %s to return type %s.",
+ gsk_sl_type_get_name (gsk_sl_expression_get_return_type
(return_node->value)),
+ gsk_sl_type_get_name (return_type));
+ gsk_sl_node_unref (node);
+ node = NULL;
+ break;
+ }
}
}
- break;
+ break;
+
+ default:
+ {
+ GskSlExpression * expression = gsk_sl_expression_parse (scope, preproc);
+
+ if (expression)
+ {
+ GskSlNodeExpression *node_expression;
+
+ node_expression = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION);
+ node_expression->expression = expression;
+
+ node = (GskSlNode *) node_expression;
+ }
+ else
+ {
+ return NULL;
+ }
}
- }
+ break;
+ }
-out:
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) function);
+ if (node == NULL)
+ return NULL;
- if (result)
- {
- return (GskSlNode *) function;
- }
- else
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
{
- gsk_sl_node_unref ((GskSlNode *) function);
+ gsk_sl_preprocessor_error (preproc, "No semicolon at end of statement.");
+ gsk_sl_node_unref (node);
return NULL;
}
+ gsk_sl_preprocessor_consume (preproc, (GskSlNode *) node);
+
+ return node;
}
GskSlNode *
diff --git a/gsk/gskslnodeprivate.h b/gsk/gskslnodeprivate.h
index ead2280..5cb00c4 100644
--- a/gsk/gskslnodeprivate.h
+++ b/gsk/gskslnodeprivate.h
@@ -41,7 +41,7 @@ struct _GskSlNodeClass {
GskSpvWriter *writer);
};
-GskSlNode * gsk_sl_node_parse_function_definition (GskSlScope *scope,
+GskSlNode * gsk_sl_node_parse_statement (GskSlScope *scope,
GskSlPreprocessor *preproc);
GskSlNode * gsk_sl_node_ref (GskSlNode *node);
diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c
index dcb0f99..8a1d6de 100644
--- a/gsk/gskslprogram.c
+++ b/gsk/gskslprogram.c
@@ -20,10 +20,12 @@
#include "gskslprogramprivate.h"
+#include "gskslfunctionprivate.h"
#include "gskslnodeprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
+#include "gsksltypeprivate.h"
#include "gskspvwriterprivate.h"
struct _GskSlProgram {
@@ -59,7 +61,48 @@ gsk_sl_program_class_init (GskSlProgramClass *klass)
static void
gsk_sl_program_init (GskSlProgram *program)
{
- program->scope = gsk_sl_scope_new (NULL);
+ program->scope = gsk_sl_scope_new (NULL, NULL);
+}
+
+static gboolean
+gsk_sl_program_parse_declaration (GskSlProgram *program,
+ GskSlScope *scope,
+ GskSlPreprocessor *preproc)
+{
+ GskSlType *type;
+ GskSlFunction *function;
+ const GskSlToken *token;
+ char *name;
+
+ type = gsk_sl_type_new_parse (preproc);
+ if (type == NULL)
+ {
+ gsk_sl_preprocessor_consume (preproc, program);
+ return FALSE;
+ }
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ gsk_sl_preprocessor_error (preproc, "Expected a function name");
+ gsk_sl_type_unref (type);
+ return FALSE;
+ }
+
+ name = g_strdup (token->str);
+ gsk_sl_preprocessor_consume (preproc, program);
+
+ function = gsk_sl_function_new_parse (scope,
+ preproc,
+ type,
+ name);
+ if (function)
+ program->functions = g_slist_append (program->functions, function);
+
+ gsk_sl_type_unref (type);
+ g_free (name);
+
+ return function != NULL;
}
gboolean
@@ -67,26 +110,16 @@ gsk_sl_program_parse (GskSlProgram *program,
GskSlPreprocessor *preproc)
{
const GskSlToken *token;
- gboolean result = TRUE;
+ gboolean success = TRUE;
for (token = gsk_sl_preprocessor_get (preproc);
!gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
token = gsk_sl_preprocessor_get (preproc))
{
- GskSlNode *node = gsk_sl_node_parse_function_definition (program->scope, preproc);
-
- if (node)
- {
- program->functions = g_slist_append (program->functions, node);
- }
- else
- {
- gsk_sl_preprocessor_consume (preproc, (GskSlNode *) program);
- result = FALSE;
- }
+ success &= gsk_sl_program_parse_declaration (program, program->scope, preproc);
}
- return result;
+ return success;
}
void
@@ -105,7 +138,7 @@ gsk_sl_program_print (GskSlProgram *program,
{
if (l != program->functions || program->declarations != NULL)
g_string_append (string, "\n");
- gsk_sl_node_print (l->data, string);
+ gsk_sl_function_print (l->data, string);
}
}
diff --git a/gsk/gskslscope.c b/gsk/gskslscope.c
index 0a7b03f..3e2be75 100644
--- a/gsk/gskslscope.c
+++ b/gsk/gskslscope.c
@@ -20,6 +20,7 @@
#include "gskslscopeprivate.h"
+#include "gsksltypeprivate.h"
#include "gskslvariableprivate.h"
#include <string.h>
@@ -29,12 +30,14 @@ struct _GskSlScope
int ref_count;
GskSlScope *parent;
+ GskSlType *return_type;
GHashTable *variables;
};
GskSlScope *
-gsk_sl_scope_new (GskSlScope *parent)
+gsk_sl_scope_new (GskSlScope *parent,
+ GskSlType *return_type)
{
GskSlScope *scope;
@@ -43,6 +46,8 @@ gsk_sl_scope_new (GskSlScope *parent)
if (parent)
scope->parent = gsk_sl_scope_ref (parent);
+ if (return_type)
+ scope->return_type = gsk_sl_type_ref (return_type);
scope->variables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)
gsk_sl_variable_unref);
return scope;
@@ -72,10 +77,18 @@ gsk_sl_scope_unref (GskSlScope *scope)
if (scope->parent)
gsk_sl_scope_unref (scope->parent);
+ if (scope->return_type)
+ gsk_sl_type_unref (scope->return_type);
g_slice_free (GskSlScope, scope);
}
+GskSlType *
+gsk_sl_scope_get_return_type (const GskSlScope *scope)
+{
+ return scope->return_type;
+}
+
void
gsk_sl_scope_add_variable (GskSlScope *scope,
GskSlVariable *variable)
diff --git a/gsk/gskslscopeprivate.h b/gsk/gskslscopeprivate.h
index 1106075..9a41bef 100644
--- a/gsk/gskslscopeprivate.h
+++ b/gsk/gskslscopeprivate.h
@@ -25,11 +25,14 @@
G_BEGIN_DECLS
-GskSlScope * gsk_sl_scope_new (GskSlScope *parent);
+GskSlScope * gsk_sl_scope_new (GskSlScope *parent,
+ GskSlType *return_type);
GskSlScope * gsk_sl_scope_ref (GskSlScope *scope);
void gsk_sl_scope_unref (GskSlScope *scope);
+GskSlType * gsk_sl_scope_get_return_type (const GskSlScope *scope);
+
void gsk_sl_scope_add_variable (GskSlScope *scope,
GskSlVariable *variable);
GskSlVariable * gsk_sl_scope_lookup_variable (GskSlScope *scope,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]