From c22b36d2b5420ded7b5ad07db781be189bd9a8f5 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 28 Sep 2017 23:11:34 +0200 Subject: [PATCH] gskslfunction: Parse arguments --- gsk/gskslfunction.c | 111 ++++++++++++++++++++++++++++++++++++++++++-- gsk/gskslnode.c | 9 +++- 2 files changed, 113 insertions(+), 7 deletions(-) diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c index dd914259c3..b841579fce 100644 --- a/gsk/gskslfunction.c +++ b/gsk/gskslfunction.c @@ -21,10 +21,12 @@ #include "gskslfunctionprivate.h" #include "gskslnodeprivate.h" +#include "gskslpointertypeprivate.h" #include "gskslpreprocessorprivate.h" #include "gskslscopeprivate.h" #include "gsksltokenizerprivate.h" #include "gsksltypeprivate.h" +#include "gskslvariableprivate.h" #include "gskspvwriterprivate.h" static GskSlFunction * @@ -220,6 +222,8 @@ struct _GskSlFunctionDeclared { GskSlScope *scope; GskSlType *return_type; char *name; + GskSlVariable **arguments; + gsize n_arguments; GSList *statements; }; @@ -227,7 +231,11 @@ static void gsk_sl_function_declared_free (GskSlFunction *function) { GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function; + guint i; + for (i = 0; i < declared->n_arguments; i++) + gsk_sl_variable_unref (declared->arguments[i]); + g_free (declared->arguments); if (declared->scope) gsk_sl_scope_unref (declared->scope); if (declared->return_type) @@ -260,12 +268,19 @@ gsk_sl_function_declared_print (const GskSlFunction *function, { const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function; GSList *l; + guint i; 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, " ("); + for (i = 0; i < declared->n_arguments; i++) + { + if (i > 0) + g_string_append (string, ", "); + gsk_sl_variable_print (declared->arguments[i], string); + } g_string_append (string, ")\n"); g_string_append (string, "{\n"); @@ -284,10 +299,34 @@ gsk_sl_function_declared_matches (const GskSlFunction *function, gsize n_arguments, GError **error) { - if (n_arguments > 0) + const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function; + guint i; + + if (n_arguments != declared->n_arguments) { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Function only takes %u arguments.", 0); - return FALSE; + g_set_error (error, + GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH, + "Function %s needs %"G_GSIZE_FORMAT" arguments, but %"G_GSIZE_FORMAT" given.", + declared->name, + declared->n_arguments, + n_arguments); + return FALSE; + } + + for (i = 0; i < n_arguments; i++) + { + GskSlType *type = gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declared->arguments[i])); + + if (!gsk_sl_type_can_convert (type, arguments[i])) + { + g_set_error (error, + GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH, + "Cannot convert argument %u from %s to %s.", + i, + gsk_sl_type_get_name (arguments[i]), + gsk_sl_type_get_name (type)); + return FALSE; + } } return TRUE; @@ -385,7 +424,71 @@ gsk_sl_function_new_parse (GskSlScope *scope, } gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function); + function->scope = gsk_sl_scope_new (scope, function->return_type); + token = gsk_sl_preprocessor_get (preproc); + if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN)) + { + GPtrArray *arguments = g_ptr_array_new (); + + while (TRUE) + { + GskSlDecorations decoration; + GskSlType *type; + GskSlVariable *variable; + + gsk_sl_decoration_list_parse (scope, + preproc, + &decoration); + + type = gsk_sl_type_new_parse (scope, preproc); + + token = gsk_sl_preprocessor_get (preproc); + if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER)) + { + GskSlPointerType *pointer_type; + guint i; + + if (gsk_sl_scope_lookup_variable (function->scope, token->str)) + { + for (i = 0; i < function->n_arguments; i++) + { + if (g_str_equal (gsk_sl_variable_get_name (g_ptr_array_index (arguments, i)), token->str)) + { + gsk_sl_preprocessor_error (preproc, DECLARATION, "Duplicate argument name \"%s\".", token->str); + break; + } + } + if (i == arguments->len) + gsk_sl_preprocessor_warn (preproc, SHADOW, "Function argument \"%s\" shadows global variable of same name.", token->str); + } + + pointer_type = gsk_sl_pointer_type_new (type, TRUE, decoration.values[GSK_SL_DECORATION_CALLER_ACCESS].value); + variable = gsk_sl_variable_new (pointer_type, g_strdup (token->str), NULL, decoration.values[GSK_SL_DECORATION_CONST].set); + gsk_sl_pointer_type_unref (pointer_type); + g_ptr_array_add (arguments, variable); + + gsk_sl_scope_add_variable (function->scope, variable); + gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function); + } + else + { + gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected an identifier as the variable name."); + } + + gsk_sl_type_unref (type); + + token = gsk_sl_preprocessor_get (preproc); + if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA)) + break; + + gsk_sl_preprocessor_consume (preproc, (GskSlNode *) function); + } + + function->n_arguments = arguments->len; + function->arguments = (GskSlVariable **) g_ptr_array_free (arguments, FALSE); + } + if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN)) { gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected a closing \")\""); @@ -407,8 +510,6 @@ gsk_sl_function_new_parse (GskSlScope *scope, } 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)) diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c index 32ae89f890..2f33f854fe 100644 --- a/gsk/gskslnode.c +++ b/gsk/gskslnode.c @@ -382,11 +382,11 @@ gsk_sl_node_parse_statement (GskSlScope *scope, case GSK_SL_TOKEN_DMAT4X3: case GSK_SL_TOKEN_DMAT4X4: case GSK_SL_TOKEN_STRUCT: - case GSK_SL_TOKEN_IDENTIFIER: { GskSlType *type; GskSlDecorations decoration; +its_a_type: gsk_sl_decoration_list_parse (scope, preproc, &decoration); @@ -458,10 +458,15 @@ gsk_sl_node_parse_statement (GskSlScope *scope, } break; + case GSK_SL_TOKEN_IDENTIFIER: + if (gsk_sl_scope_lookup_type (scope, token->str)) + goto its_a_type; + /* else fall through*/ + default: { GskSlNodeExpression *node_expression; - + node_expression = gsk_sl_node_new (GskSlNodeExpression, &GSK_SL_NODE_EXPRESSION); node_expression->expression = gsk_sl_expression_parse (scope, preproc);