diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h index 4a23007cc5..a0422604a4 100644 --- a/gsk/gskslcompiler.h +++ b/gsk/gskslcompiler.h @@ -28,6 +28,7 @@ G_BEGIN_DECLS typedef enum { + GSK_SL_COMPILER_ERROR_ARGUMENT_COUNT, GSK_SL_COMPILER_ERROR_CONSTANT, GSK_SL_COMPILER_ERROR_DECLARATION, GSK_SL_COMPILER_ERROR_PREPROCESSOR, diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c index 9c9de365f0..973328afe7 100644 --- a/gsk/gskslexpression.c +++ b/gsk/gskslexpression.c @@ -1265,6 +1265,19 @@ gsk_sl_expression_error_new (void) return (GskSlExpression *) constant; } +static gsize +gsk_sl_constructor_get_args_by_type (const GskSlType *type) +{ + if (gsk_sl_type_is_scalar (type)) + return 1; + else if (gsk_sl_type_is_vector (type)) + return gsk_sl_type_get_length (type); + else if (gsk_sl_type_is_matrix (type)) + return gsk_sl_type_get_length (type) * gsk_sl_constructor_get_args_by_type (gsk_sl_type_get_index_type (type)); + else + return 0; +} + GskSlExpression * gsk_sl_expression_parse_function_call (GskSlScope *scope, GskSlPreprocessor *stream, @@ -1274,6 +1287,7 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope, const GskSlToken *token; GskSlType **types; GError *error = NULL; + gssize missing_args; /* only used for builtin constructors */ guint i; call = gsk_sl_expression_new (GskSlExpressionFunctionCall, &GSK_SL_EXPRESSION_FUNCTION_CALL); @@ -1287,6 +1301,11 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope, } gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call); + if (function && gsk_sl_function_is_builtin_constructor (function)) + missing_args = gsk_sl_constructor_get_args_by_type (gsk_sl_function_get_return_type (function)); + else + missing_args = -1; + token = gsk_sl_preprocessor_get (stream); if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN)) { @@ -1299,12 +1318,49 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope, g_ptr_array_add (arguments, expression); + if (function == NULL) + { + /* no checking necessary */ + } + if (missing_args == 0) + { + gsk_sl_preprocessor_error (stream, ARGUMENT_COUNT, + "Too many arguments given to builtin constructor, only the first %u are necessary.", + arguments->len); + function = NULL; + } + else if (missing_args > 0) + { + GskSlType *type = gsk_sl_expression_get_return_type (expression); + gsize provided = gsk_sl_constructor_get_args_by_type (type); + + if (provided == 0) + { + gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, + "Invalid type %s for builtin constructor", + gsk_sl_type_get_name (type)); + function = NULL; + } + else + { + missing_args -= MIN (missing_args, provided); + } + } + token = gsk_sl_preprocessor_get (stream); if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA)) break; gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call); } + if (missing_args > 0) + { + gsk_sl_preprocessor_error (stream, ARGUMENT_COUNT, + "Not enough arguments given to builtin constructor, %"G_GSIZE_FORMAT" are missing.", + missing_args); + function = NULL; + } + call->n_arguments = arguments->len; call->arguments = (GskSlExpression **) g_ptr_array_free (arguments, FALSE); } @@ -1312,7 +1368,7 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope, 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 (function && !gsk_sl_function_matches (function, types, call->n_arguments, &error)) + if (function && missing_args < 0 && !gsk_sl_function_matches (function, types, call->n_arguments, &error)) { gsk_sl_preprocessor_emit_error (stream, TRUE, gsk_sl_preprocessor_get_location (stream), error); g_clear_error (&error); diff --git a/gsk/gskslfunction.c b/gsk/gskslfunction.c index 624cf812e9..75d4f1bf6e 100644 --- a/gsk/gskslfunction.c +++ b/gsk/gskslfunction.c @@ -80,64 +80,25 @@ gsk_sl_function_builtin_constructor_get_name (const GskSlFunction *function) return gsk_sl_type_get_name (builtin_constructor->type); } +static gsize +gsk_sl_function_builtin_constructor_get_n_arguments (const GskSlFunction *function) +{ + return 0; +} + +static GskSlType * +gsk_sl_function_builtin_constructor_get_argument_type (const GskSlFunction *function, + gsize i) +{ + return NULL; +} + static void gsk_sl_function_builtin_constructor_print (const GskSlFunction *function, GString *string) { } -static guint -gsk_sl_function_builtin_get_args_by_type (const GskSlType *type) -{ - if (gsk_sl_type_is_scalar (type)) - return 1; - else if (gsk_sl_type_is_vector (type)) - return gsk_sl_type_get_length (type); - else if (gsk_sl_type_is_matrix (type)) - return gsk_sl_type_get_length (type) * gsk_sl_function_builtin_get_args_by_type (gsk_sl_type_get_index_type (type)); - else - return 0; -} - -static gboolean -gsk_sl_function_builtin_constructor_matches (const GskSlFunction *function, - GskSlType **arguments, - gsize n_arguments, - GError **error) -{ - const GskSlFunctionBuiltinConstructor *builtin_constructor = (const GskSlFunctionBuiltinConstructor *) function; - guint needed, provided; - gsize i; - - if (n_arguments == 1 && gsk_sl_type_is_scalar (arguments[0])) - return TRUE; - - needed = gsk_sl_function_builtin_get_args_by_type (builtin_constructor->type); - - for (i = 0; i < n_arguments; i++) - { - if (needed == 0) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Too many arguments given to builtin_constructor, only the first %"G_GSIZE_FORMAT" are necessary.", i); - return FALSE; - } - - provided = gsk_sl_function_builtin_get_args_by_type (arguments[i]); - if (provided == 0) - { - g_set_error (error, - G_FILE_ERROR, G_FILE_ERROR_FAILED, - "Invalid type %s for builtin_constructor in argument %"G_GSIZE_FORMAT, - gsk_sl_type_get_name (arguments[i]), i + 1); - return FALSE; - } - - needed -= MIN (needed, provided); - } - - return TRUE; -} - static guint32 gsk_sl_function_builtin_constructor_write_spv (const GskSlFunction *function, GskSpvWriter *writer) @@ -149,8 +110,9 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_BUILTIN_CONSTRUCTOR = { gsk_sl_function_builtin_constructor_free, gsk_sl_function_builtin_constructor_get_return_type, gsk_sl_function_builtin_constructor_get_name, + gsk_sl_function_builtin_constructor_get_n_arguments, + gsk_sl_function_builtin_constructor_get_argument_type, gsk_sl_function_builtin_constructor_print, - gsk_sl_function_builtin_constructor_matches, gsk_sl_function_builtin_constructor_write_spv, }; @@ -190,49 +152,29 @@ gsk_sl_function_constructor_get_name (const GskSlFunction *function) return gsk_sl_type_get_name (constructor->type); } +static gsize +gsk_sl_function_constructor_get_n_arguments (const GskSlFunction *function) +{ + const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function; + + return gsk_sl_type_get_n_members (constructor->type); +} + +static GskSlType * +gsk_sl_function_constructor_get_argument_type (const GskSlFunction *function, + gsize i) +{ + const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function; + + return gsk_sl_type_get_member_type (constructor->type, i); +} + static void gsk_sl_function_constructor_print (const GskSlFunction *function, GString *string) { } -static gboolean -gsk_sl_function_constructor_matches (const GskSlFunction *function, - GskSlType **arguments, - gsize n_arguments, - GError **error) -{ - const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function; - guint i; - - if (n_arguments != gsk_sl_type_get_n_members (constructor->type)) - { - g_set_error (error, - GSK_SL_COMPILER_ERROR, GSK_SL_COMPILER_ERROR_TYPE_MISMATCH, - "Constructor for %s needs %u arguments, but %"G_GSIZE_FORMAT" given.", - gsk_sl_type_get_name (constructor->type), - gsk_sl_type_get_n_members (constructor->type), - n_arguments); - return FALSE; - } - - for (i = 0; i < n_arguments; i++) - { - if (!gsk_sl_type_can_convert (gsk_sl_type_get_member_type (constructor->type, i), 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 (gsk_sl_type_get_member_type (constructor->type, i))); - return FALSE; - } - } - - return TRUE; -} - static guint32 gsk_sl_function_constructor_write_spv (const GskSlFunction *function, GskSpvWriter *writer) @@ -244,8 +186,9 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_CONSTRUCTOR = { gsk_sl_function_constructor_free, gsk_sl_function_constructor_get_return_type, gsk_sl_function_constructor_get_name, + gsk_sl_function_constructor_get_n_arguments, + gsk_sl_function_constructor_get_argument_type, gsk_sl_function_constructor_print, - gsk_sl_function_constructor_matches, gsk_sl_function_constructor_write_spv, }; @@ -299,6 +242,22 @@ gsk_sl_function_declared_get_name (const GskSlFunction *function) return declared->name; } +static gsize +gsk_sl_function_declared_get_n_arguments (const GskSlFunction *function) +{ + const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function; + + return declared->n_arguments; +} + +static GskSlType * +gsk_sl_function_declared_get_argument_type (const GskSlFunction *function, + gsize i) +{ + const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function; + + return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declared->arguments[i])); +} static void gsk_sl_function_declared_print (const GskSlFunction *function, GString *string) @@ -330,45 +289,6 @@ gsk_sl_function_declared_print (const GskSlFunction *function, g_string_append (string, "}\n"); } -static gboolean -gsk_sl_function_declared_matches (const GskSlFunction *function, - GskSlType **arguments, - gsize n_arguments, - GError **error) -{ - const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function; - guint i; - - if (n_arguments != declared->n_arguments) - { - 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; -} - static guint32 gsk_sl_function_declared_write_spv (const GskSlFunction *function, GskSpvWriter *writer) @@ -421,8 +341,9 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_DECLARED = { gsk_sl_function_declared_free, gsk_sl_function_declared_get_return_type, gsk_sl_function_declared_get_name, + gsk_sl_function_declared_get_n_arguments, + gsk_sl_function_declared_get_argument_type, gsk_sl_function_declared_print, - gsk_sl_function_declared_matches, gsk_sl_function_declared_write_spv, }; @@ -609,6 +530,12 @@ gsk_sl_function_unref (GskSlFunction *function) function->class->free (function); } +gboolean +gsk_sl_function_is_builtin_constructor (const GskSlFunction *function) +{ + return function->class == &GSK_SL_FUNCTION_BUILTIN_CONSTRUCTOR; +} + GskSlType * gsk_sl_function_get_return_type (const GskSlFunction *function) { @@ -621,6 +548,19 @@ gsk_sl_function_get_name (const GskSlFunction *function) return function->class->get_name (function); } +gsize +gsk_sl_function_get_n_arguments (const GskSlFunction *function) +{ + return function->class->get_n_arguments (function); +} + +GskSlType * +gsk_sl_function_get_argument_type (const GskSlFunction *function, + gsize i) +{ + return function->class->get_argument_type (function, i); +} + void gsk_sl_function_print (const GskSlFunction *function, GString *string) @@ -634,7 +574,34 @@ gsk_sl_function_matches (const GskSlFunction *function, gsize n_arguments, GError **error) { - return function->class->matches (function, arguments, n_arguments, error); + guint i; + + if (n_arguments != gsk_sl_function_get_n_arguments (function)) + { + 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.", + gsk_sl_function_get_name (function), + gsk_sl_function_get_n_arguments (function), + n_arguments); + return FALSE; + } + + for (i = 0; i < n_arguments; i++) + { + if (!gsk_sl_type_can_convert (gsk_sl_function_get_argument_type (function, i), 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 + 1, + gsk_sl_type_get_name (arguments[i]), + gsk_sl_type_get_name (gsk_sl_function_get_argument_type (function, i))); + return FALSE; + } + } + + return TRUE; } guint32 diff --git a/gsk/gskslfunctionprivate.h b/gsk/gskslfunctionprivate.h index 9e28374c96..ce38b8ebe0 100644 --- a/gsk/gskslfunctionprivate.h +++ b/gsk/gskslfunctionprivate.h @@ -39,12 +39,11 @@ struct _GskSlFunctionClass { GskSlType * (* get_return_type) (const GskSlFunction *function); const char * (* get_name) (const GskSlFunction *function); + gsize (* get_n_arguments) (const GskSlFunction *function); + GskSlType * (* get_argument_type) (const GskSlFunction *function, + gsize i); 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); }; @@ -58,11 +57,16 @@ GskSlFunction * gsk_sl_function_new_parse (GskSlScope GskSlFunction * gsk_sl_function_ref (GskSlFunction *function); void gsk_sl_function_unref (GskSlFunction *function); +gboolean gsk_sl_function_is_builtin_constructor (const GskSlFunction *function); + void gsk_sl_function_print (const GskSlFunction *function, GString *string); const char * gsk_sl_function_get_name (const GskSlFunction *function); GskSlType * gsk_sl_function_get_return_type (const GskSlFunction *function); +gsize gsk_sl_function_get_n_arguments (const GskSlFunction *function); +GskSlType * gsk_sl_function_get_argument_type (const GskSlFunction *function, + gsize i); gboolean gsk_sl_function_matches (const GskSlFunction *function, GskSlType **arguments, gsize n_arguments,