gskslfunction: Reorganize gsk_sl_function_matches()
This is the first step towards implementing function overloading. Instead of having the matches() vfunc the code now can query argument type and count and uses this to implement a generic matches(). Constructors are checked seperately and manually. They also report 0 arguments.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user