gsksl: Builtin constructors are no longer functions

They don't obey the laws that govern constructors (argument promotion,
constant amount of predefined types of arguments and so on).
So we turn constructor calls into their own expression type.

This also dimplifies function call validation because we don't have to
do two-in-one with constructors in there.

And while doing that, also fix up the rules that govern constructor
arguments: Matrixes aren't allowed as arguments for matrixes unless
they're the first and only argument.
And if scalars are the first and only argument, they behave differently
than they would otherwise.
This commit is contained in:
Benjamin Otte
2017-10-03 03:58:40 +02:00
parent a50d932150
commit 0c567d6c28
5 changed files with 379 additions and 174 deletions

View File

@@ -713,6 +713,227 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_REFERENCE = {
gsk_sl_expression_reference_write_spv
};
/* CONSTRUCTOR CALL */
typedef struct _GskSlExpressionConstructor GskSlExpressionConstructor;
struct _GskSlExpressionConstructor {
GskSlExpression parent;
GskSlType *type;
GskSlExpression **arguments;
guint n_arguments;
};
static void
gsk_sl_expression_constructor_free (GskSlExpression *expression)
{
GskSlExpressionConstructor *constructor = (GskSlExpressionConstructor *) expression;
guint i;
for (i = 0; i < constructor->n_arguments; i++)
{
gsk_sl_expression_unref (constructor->arguments[i]);
}
g_free (constructor->arguments);
gsk_sl_type_unref (constructor->type);
g_slice_free (GskSlExpressionConstructor, constructor);
}
static void
gsk_sl_expression_constructor_print (const GskSlExpression *expression,
GskSlPrinter *printer)
{
const GskSlExpressionConstructor *constructor = (const GskSlExpressionConstructor *) expression;
guint i;
gsk_sl_printer_append (printer, gsk_sl_type_get_name (constructor->type));
gsk_sl_printer_append (printer, " (");
for (i = 0; i < constructor->n_arguments; i++)
{
if (i > 0)
gsk_sl_printer_append (printer, ", ");
gsk_sl_expression_print (constructor->arguments[i], printer);
}
gsk_sl_printer_append (printer, ")");
}
static GskSlType *
gsk_sl_expression_constructor_get_return_type (const GskSlExpression *expression)
{
const GskSlExpressionConstructor *constructor = (const GskSlExpressionConstructor *) expression;
return constructor->type;
}
static GskSlValue *
gsk_sl_expression_constructor_get_constant (const GskSlExpression *expression)
{
const GskSlExpressionConstructor *constructor = (const GskSlExpressionConstructor *) expression;
GskSlType *type = constructor->type;
GskSlValue *values[constructor->n_arguments];
GskSlValue *result;
guint i;
for (i = 0; i < constructor->n_arguments; i++)
{
values[i] = gsk_sl_expression_get_constant (constructor->arguments[i]);
if (values[i] == NULL)
{
guint j;
for (j = 0; j < i; j++)
gsk_sl_value_free (values[j]);
return NULL;
}
}
result = gsk_sl_value_new (type);
if (constructor->n_arguments == 1 && gsk_sl_type_is_scalar (gsk_sl_value_get_type (values[0])))
{
GskSlScalarType sscalar, dscalar;
guchar *sdata, *ddata;
gsize dstride;
sscalar = gsk_sl_type_get_scalar_type (gsk_sl_value_get_type (values[0]));
sdata = gsk_sl_value_get_data (values[0]);
dscalar = gsk_sl_type_get_scalar_type (type);
ddata = gsk_sl_value_get_data (result);
dstride = gsk_sl_scalar_type_get_size (dscalar);
if (gsk_sl_type_is_scalar (type))
{
gsk_sl_scalar_type_convert_value (dscalar, ddata, sscalar, sdata);
}
else if (gsk_sl_type_is_vector (type))
{
gsize i;
for (i = 0; i < gsk_sl_type_get_n_components (type); i++)
{
gsk_sl_scalar_type_convert_value (dscalar, ddata + i * dstride, sscalar, sdata);
}
}
else if (gsk_sl_type_is_matrix (type))
{
gsize i, n, step;
n = gsk_sl_type_get_n_components (type);
step = n / gsk_sl_type_get_length (type) + 1;
for (i = 0; i < n; i += step)
{
gsk_sl_scalar_type_convert_value (dscalar, ddata + i * dstride, sscalar, sdata);
}
}
}
else if (constructor->n_arguments == 1 && gsk_sl_type_is_matrix (gsk_sl_value_get_type (values[0])) && gsk_sl_type_is_matrix (type))
{
GskSlScalarType sscalar, dscalar;
guchar *sdata, *ddata;
gsize drows, dcols, srows, scols, r, c, sstride, dstride;
sscalar = gsk_sl_type_get_scalar_type (gsk_sl_value_get_type (values[0]));
sstride = gsk_sl_scalar_type_get_size (sscalar);
sdata = gsk_sl_value_get_data (values[0]);
scols = gsk_sl_type_get_length (gsk_sl_value_get_type (values[0]));
srows = gsk_sl_type_get_length (gsk_sl_value_get_type (values[0]));
dscalar = gsk_sl_type_get_scalar_type (type);
dstride = gsk_sl_scalar_type_get_size (dscalar);
ddata = gsk_sl_value_get_data (result);
dcols = gsk_sl_type_get_length (type);
drows = gsk_sl_type_get_length (gsk_sl_type_get_index_type (type));
for (c = 0; c < scols; c++)
{
for (r = 0; r < srows; r++)
{
gsk_sl_scalar_type_convert_value (dscalar,
ddata + dstride * (c * drows + r),
sscalar,
sdata + sstride * (c * srows + r));
}
for (; r < drows; r++)
{
gsk_sl_scalar_type_convert_value (dscalar,
ddata + dstride * (c * drows + r),
GSK_SL_FLOAT,
&(float) { c == r ? 1 : 0 });
}
}
for (; c < dcols; c++)
{
for (r = 0; r < drows; r++)
{
gsk_sl_scalar_type_convert_value (dscalar,
ddata + dstride * (c * drows + r),
GSK_SL_FLOAT,
&(float) { c == r ? 1 : 0 });
}
}
}
else
{
GskSlScalarType sscalar, dscalar;
guchar *sdata, *ddata;
gsize i, n, j, si, sn, sstride, dstride;
dscalar = gsk_sl_type_get_scalar_type (type);
dstride = gsk_sl_scalar_type_get_size (dscalar);
n = gsk_sl_type_get_n_components (type);
ddata = gsk_sl_value_get_data (result);
sscalar = GSK_SL_VOID;
sdata = NULL;
sstride = 0;
j = 0;
sn = 0;
si = 0;
for (i = 0; i < n; i++)
{
if (si == sn)
{
sscalar = gsk_sl_type_get_scalar_type (gsk_sl_value_get_type (values[j]));
sstride = gsk_sl_scalar_type_get_size (sscalar);
sdata = gsk_sl_value_get_data (values[j]);
si = 0;
sn = gsk_sl_type_get_n_components (gsk_sl_value_get_type (values[j]));
j++;
}
gsk_sl_scalar_type_convert_value (dscalar,
ddata + dstride * i,
sscalar,
sdata + sstride * si);
si++;
}
}
for (i = 0; i < constructor->n_arguments; i++)
gsk_sl_value_free (values[i]);
return result;
}
static guint32
gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
GskSpvWriter *writer)
{
g_assert_not_reached ();
return 0;
}
static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTRUCTOR = {
gsk_sl_expression_constructor_free,
gsk_sl_expression_constructor_print,
gsk_sl_expression_constructor_get_return_type,
gsk_sl_expression_constructor_get_constant,
gsk_sl_expression_constructor_write_spv
};
/* FUNCTION_CALL */
typedef struct _GskSlExpressionFunctionCall GskSlExpressionFunctionCall;
@@ -1265,15 +1486,123 @@ gsk_sl_expression_error_new (void)
return (GskSlExpression *) constant;
}
GskSlExpression *
gsk_sl_expression_parse_constructor (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlType *type)
{
GskSlExpressionConstructor *call;
const GskSlToken *token;
gssize missing_args;
GPtrArray *arguments;
call = gsk_sl_expression_new (GskSlExpressionConstructor, &GSK_SL_EXPRESSION_CONSTRUCTOR);
call->type = gsk_sl_type_ref (type);
token = gsk_sl_preprocessor_get (stream);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
{
gsk_sl_preprocessor_error (stream, SYNTAX, "Expected opening \"(\" when calling function.");
gsk_sl_expression_unref ((GskSlExpression *) call);
return gsk_sl_expression_error_new ();
}
gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
missing_args = gsk_sl_type_get_n_components (type);
arguments = g_ptr_array_new ();
token = gsk_sl_preprocessor_get (stream);
while (TRUE)
{
GskSlExpression *expression = gsk_sl_expression_parse_assignment (scope, stream);
if (missing_args == 0)
{
gsk_sl_preprocessor_error (stream, ARGUMENT_COUNT,
"Too many arguments given to builtin constructor, need only %u.",
arguments->len);
missing_args = -1;
}
else if (missing_args > 0)
{
GskSlType *return_type = gsk_sl_expression_get_return_type (expression);
gsize provided = gsk_sl_type_get_n_components (return_type);
if (provided == 0)
{
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
"Invalid type %s for builtin constructor",
gsk_sl_type_get_name (return_type));
missing_args = -1;
}
else if (gsk_sl_type_is_matrix (return_type) &&
gsk_sl_type_is_matrix (type))
{
if (arguments->len == 0)
{
missing_args = 0;
}
else
{
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
"Matrix type %s only valid as first argument for %s",
gsk_sl_type_get_name (return_type),
gsk_sl_type_get_name (type));
missing_args = -1;
}
}
else
{
missing_args -= MIN (missing_args, provided);
}
}
g_ptr_array_add (arguments, expression);
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)
{
if (arguments->len != 1 || !gsk_sl_type_is_scalar (gsk_sl_expression_get_return_type (g_ptr_array_index (arguments, 0))))
{
gsk_sl_preprocessor_error (stream, ARGUMENT_COUNT,
"Not enough arguments given to builtin constructor, %"G_GSIZE_FORMAT" are missing.",
missing_args);
missing_args = -1;
}
}
call->n_arguments = arguments->len;
call->arguments = (GskSlExpression **) g_ptr_array_free (arguments, FALSE);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
gsk_sl_preprocessor_error (stream, SYNTAX, "Expected closing \")\" after arguments.");
gsk_sl_preprocessor_sync (stream, GSK_SL_TOKEN_RIGHT_PAREN);
}
gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
if (missing_args < 0)
{
gsk_sl_expression_unref ((GskSlExpression *) call);
return gsk_sl_expression_error_new ();
}
return (GskSlExpression *) call;
}
GskSlExpression *
gsk_sl_expression_parse_function_call (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlFunctionMatcher *matcher,
GskSlFunction *function)
GskSlFunctionMatcher *matcher)
{
GskSlExpressionFunctionCall *call;
const GskSlToken *token;
gssize missing_args; /* only used for builtin constructors */
call = gsk_sl_expression_new (GskSlExpressionFunctionCall, &GSK_SL_EXPRESSION_FUNCTION_CALL);
@@ -1286,11 +1615,6 @@ 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_type_get_n_components (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))
{
@@ -1301,7 +1625,7 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope,
{
GskSlExpression *expression = gsk_sl_expression_parse_assignment (scope, stream);
if (function == NULL && matcher == NULL)
if (matcher == NULL)
{
/* no checking necessary */
}
@@ -1311,44 +1635,11 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope,
gsk_sl_function_matcher_match_argument (matcher, arguments->len, type);
if (!gsk_sl_function_matcher_has_matches (matcher))
{
if (function)
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
"Cannot convert argument %u from %s to %s.",
arguments->len + 1,
gsk_sl_type_get_name (type),
gsk_sl_type_get_name (gsk_sl_function_get_argument_type (function, arguments->len)));
else
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
"No overloaded function available that matches the first %u arguments",
arguments->len + 1);
matcher = NULL;
function = NULL;
}
}
else 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_type_get_n_components (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);
"No overloaded function available that matches the first %u arguments",
arguments->len + 1);
matcher = NULL;
}
}
@@ -1360,14 +1651,6 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope,
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);
}
@@ -1377,23 +1660,22 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope,
gsk_sl_function_matcher_match_n_arguments (matcher, call->n_arguments);
if (!gsk_sl_function_matcher_has_matches (matcher))
{
if (function)
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
"Function %s needs %"G_GSIZE_FORMAT" arguments, but %u given.",
gsk_sl_function_get_name (function),
gsk_sl_function_get_n_arguments (function),
call->n_arguments);
else
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
"No overloaded function available that matches this call");
function = NULL;
gsk_sl_preprocessor_error (stream, TYPE_MISMATCH,
"No overloaded function available with %u arguments.",
call->n_arguments);
matcher = NULL;
}
else
{
function = gsk_sl_function_matcher_get_match (matcher);
if (function == NULL)
gsk_sl_preprocessor_error (stream, UNIQUENESS,
"Cannot find unique match for overloaded function.");
call->function = gsk_sl_function_matcher_get_match (matcher);
if (call->function)
gsk_sl_function_ref (call->function);
else
{
gsk_sl_preprocessor_error (stream, UNIQUENESS,
"Cannot find unique match for overloaded function.");
matcher = NULL;
}
}
}
@@ -1401,16 +1683,16 @@ gsk_sl_expression_parse_function_call (GskSlScope *scope,
{
gsk_sl_preprocessor_error (stream, SYNTAX, "Expected closing \")\" after arguments.");
gsk_sl_preprocessor_sync (stream, GSK_SL_TOKEN_RIGHT_PAREN);
matcher = NULL;
}
gsk_sl_preprocessor_consume (stream, (GskSlExpression *) call);
if (function == NULL)
if (matcher == NULL)
{
gsk_sl_expression_unref ((GskSlExpression *) call);
return gsk_sl_expression_error_new ();
}
call->function = gsk_sl_function_ref (function);
return (GskSlExpression *) call;
}
@@ -1440,7 +1722,7 @@ gsk_sl_expression_parse_primary (GskSlScope *scope,
gsk_sl_preprocessor_consume (stream, NULL);
constructor = gsk_sl_function_new_constructor (type);
gsk_sl_function_matcher_init (&matcher, g_list_prepend (NULL, constructor));
expr = gsk_sl_expression_parse_function_call (scope, stream, &matcher, constructor);
expr = gsk_sl_expression_parse_function_call (scope, stream, &matcher);
gsk_sl_function_matcher_finish (&matcher);
gsk_sl_function_unref (constructor);
@@ -1460,9 +1742,7 @@ gsk_sl_expression_parse_primary (GskSlScope *scope,
if (!gsk_sl_function_matcher_has_matches (&matcher))
gsk_sl_preprocessor_error (stream, DECLARATION, "No function named \"%s\".", name);
expr = gsk_sl_expression_parse_function_call (scope, stream,
&matcher,
gsk_sl_function_matcher_get_match (&matcher));
expr = gsk_sl_expression_parse_function_call (scope, stream, &matcher);
gsk_sl_function_matcher_finish (&matcher);
}
@@ -1584,15 +1864,28 @@ gsk_sl_expression_parse_primary (GskSlScope *scope,
case GSK_SL_TOKEN_DMAT4X2:
case GSK_SL_TOKEN_DMAT4X3:
case GSK_SL_TOKEN_DMAT4X4:
{
GskSlExpression *expression;
GskSlType *type;
type = gsk_sl_type_new_parse (scope, stream);
expression = gsk_sl_expression_parse_constructor (scope, stream, type);
gsk_sl_type_unref (type);
return expression;
}
case GSK_SL_TOKEN_STRUCT:
{
GskSlFunctionMatcher matcher;
GskSlFunction *constructor;
GskSlExpression *expression;
GskSlType *type;
type = gsk_sl_type_new_parse (scope, stream);
constructor = gsk_sl_function_new_constructor (type);
expression = gsk_sl_expression_parse_function_call (scope, stream, NULL, constructor);
gsk_sl_function_matcher_init (&matcher, g_list_prepend (NULL, constructor));
expression = gsk_sl_expression_parse_function_call (scope, stream, &matcher);
gsk_sl_function_matcher_finish (&matcher);
gsk_sl_function_unref (constructor);
gsk_sl_type_unref (type);

View File

@@ -29,10 +29,12 @@ GskSlExpression * gsk_sl_expression_parse_assignment (GskSlScope
GskSlPreprocessor *stream);
GskSlExpression * gsk_sl_expression_parse_constant (GskSlScope *scope,
GskSlPreprocessor *stream);
GskSlExpression * gsk_sl_expression_parse_constructor (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlType *type);
GskSlExpression * gsk_sl_expression_parse_function_call (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlFunctionMatcher *matcher,
GskSlFunction *function);
GskSlFunctionMatcher *matcher);
GskSlExpression * gsk_sl_expression_ref (GskSlExpression *expression);
void gsk_sl_expression_unref (GskSlExpression *expression);

View File

@@ -72,78 +72,6 @@ gsk_sl_function_alloc (const GskSlFunctionClass *klass,
/* CONSTRUCTOR */
typedef struct _GskSlFunctionBuiltinConstructor GskSlFunctionBuiltinConstructor;
struct _GskSlFunctionBuiltinConstructor {
GskSlFunction parent;
GskSlType *type;
};
static void
gsk_sl_function_builtin_constructor_free (GskSlFunction *function)
{
GskSlFunctionBuiltinConstructor *builtin_constructor = (GskSlFunctionBuiltinConstructor *) function;
gsk_sl_type_unref (builtin_constructor->type);
g_slice_free (GskSlFunctionBuiltinConstructor, builtin_constructor);
}
static GskSlType *
gsk_sl_function_builtin_constructor_get_return_type (const GskSlFunction *function)
{
const GskSlFunctionBuiltinConstructor *builtin_constructor = (const GskSlFunctionBuiltinConstructor *) function;
return builtin_constructor->type;
}
static const char *
gsk_sl_function_builtin_constructor_get_name (const GskSlFunction *function)
{
const GskSlFunctionBuiltinConstructor *builtin_constructor = (const GskSlFunctionBuiltinConstructor *) 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,
GskSlPrinter *printer)
{
}
static guint32
gsk_sl_function_builtin_constructor_write_spv (const GskSlFunction *function,
GskSpvWriter *writer)
{
return 0;
}
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_write_spv,
};
/* CONSTRUCTOR */
typedef struct _GskSlFunctionConstructor GskSlFunctionConstructor;
struct _GskSlFunctionConstructor {
@@ -461,18 +389,7 @@ static const GskSlFunctionClass GSK_SL_FUNCTION_DECLARED = {
GskSlFunction *
gsk_sl_function_new_constructor (GskSlType *type)
{
if (gsk_sl_type_is_scalar (type) ||
gsk_sl_type_is_vector (type) ||
gsk_sl_type_is_matrix (type))
{
GskSlFunctionBuiltinConstructor *constructor;
constructor = gsk_sl_function_new (GskSlFunctionBuiltinConstructor, &GSK_SL_FUNCTION_BUILTIN_CONSTRUCTOR);
constructor->type = gsk_sl_type_ref (type);
return &constructor->parent;
}
else if (gsk_sl_type_is_struct (type))
if (gsk_sl_type_is_struct (type))
{
GskSlFunctionConstructor *constructor;
@@ -633,12 +550,6 @@ 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)
{

View File

@@ -35,8 +35,6 @@ 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,
GskSlPrinter *printer);

View File

@@ -757,23 +757,24 @@ its_a_type:
if (token->type == GSK_SL_TOKEN_LEFT_PAREN)
{
GskSlStatementExpression *statement_expression;
GskSlFunction *constructor;
constructor = gsk_sl_function_new_constructor (type);
statement_expression = gsk_sl_statement_new (GskSlStatementExpression, &GSK_SL_STATEMENT_EXPRESSION);
if (gsk_sl_function_is_builtin_constructor (constructor))
if (gsk_sl_type_is_scalar (type) || gsk_sl_type_is_vector (type) || gsk_sl_type_is_matrix (type))
{
statement_expression->expression = gsk_sl_expression_parse_function_call (scope, preproc, NULL, constructor);
statement_expression->expression = gsk_sl_expression_parse_constructor (scope, preproc, type);
}
else
{
GskSlFunction *constructor;
GskSlFunctionMatcher matcher;
constructor = gsk_sl_function_new_constructor (type);
gsk_sl_function_matcher_init (&matcher, g_list_prepend (NULL, constructor));
statement_expression->expression = gsk_sl_expression_parse_function_call (scope, preproc, &matcher, constructor);
statement_expression->expression = gsk_sl_expression_parse_function_call (scope, preproc, &matcher);
gsk_sl_function_matcher_finish (&matcher);
gsk_sl_function_unref (constructor);
}
statement = (GskSlStatement *) statement_expression;
gsk_sl_function_unref (constructor);
}
else
{