gskslexpression: Add gsk_sl_expression_is_assignable()

And use it to fail when parsing assignments.
This commit is contained in:
Benjamin Otte
2017-10-08 06:46:57 +02:00
parent 115182d6e6
commit bda72e2c23
2 changed files with 105 additions and 6 deletions

View File

@@ -46,6 +46,8 @@ struct _GskSlExpressionClass {
void (* print) (const GskSlExpression *expression,
GskSlPrinter *printer);
gboolean (* is_assignable) (const GskSlExpression *expression,
GError **error);
GskSlType * (* get_return_type) (const GskSlExpression *expression);
GskSlValue * (* get_constant) (const GskSlExpression *expression);
guint32 (* write_spv) (const GskSlExpression *expression,
@@ -67,6 +69,18 @@ gsk_sl_expression_alloc (const GskSlExpressionClass *klass,
}
#define gsk_sl_expression_new(_name, _klass) ((_name *) gsk_sl_expression_alloc ((_klass), sizeof (_name)))
static gboolean
gsk_sl_expression_default_is_assignable (const GskSlExpression *expression,
GError **error)
{
g_set_error (error,
GSK_SL_COMPILER_ERROR,
GSK_SL_COMPILER_ERROR_SYNTAX,
"Assignment requires l-value.");
return FALSE;
}
/* ASSIGNMENT */
typedef struct _GskSlExpressionAssignment GskSlExpressionAssignment;
@@ -130,6 +144,7 @@ gsk_sl_expression_assignment_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_ASSIGNMENT = {
gsk_sl_expression_assignment_free,
gsk_sl_expression_assignment_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_assignment_get_return_type,
gsk_sl_expression_assignment_get_constant,
gsk_sl_expression_assignment_write_spv
@@ -221,6 +236,7 @@ gsk_sl_expression_binary_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_BINARY = {
gsk_sl_expression_binary_free,
gsk_sl_expression_binary_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_binary_get_return_type,
gsk_sl_expression_binary_get_constant,
gsk_sl_expression_binary_write_spv
@@ -255,6 +271,24 @@ gsk_sl_expression_reference_print (const GskSlExpression *expression,
gsk_sl_printer_append (printer, gsk_sl_variable_get_name (reference->variable));
}
static gboolean
gsk_sl_expression_reference_is_assignable (const GskSlExpression *expression,
GError **error)
{
const GskSlExpressionReference *reference = (const GskSlExpressionReference *) expression;
if (gsk_sl_variable_is_constant (reference->variable))
{
g_set_error (error,
GSK_SL_COMPILER_ERROR,
GSK_SL_COMPILER_ERROR_CONSTANT,
"Cannot assign constant \"%s\".", gsk_sl_variable_get_name (reference->variable));
return FALSE;
}
return TRUE;
}
static GskSlType *
gsk_sl_expression_reference_get_return_type (const GskSlExpression *expression)
{
@@ -294,6 +328,7 @@ gsk_sl_expression_reference_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_REFERENCE = {
gsk_sl_expression_reference_free,
gsk_sl_expression_reference_print,
gsk_sl_expression_reference_is_assignable,
gsk_sl_expression_reference_get_return_type,
gsk_sl_expression_reference_get_constant,
gsk_sl_expression_reference_write_spv
@@ -670,6 +705,7 @@ gsk_sl_expression_constructor_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTRUCTOR = {
gsk_sl_expression_constructor_free,
gsk_sl_expression_constructor_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_constructor_get_return_type,
gsk_sl_expression_constructor_get_constant,
gsk_sl_expression_constructor_write_spv
@@ -786,6 +822,7 @@ gsk_sl_expression_function_call_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = {
gsk_sl_expression_function_call_free,
gsk_sl_expression_function_call_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_function_call_get_return_type,
gsk_sl_expression_function_call_get_constant,
gsk_sl_expression_function_call_write_spv
@@ -823,6 +860,15 @@ gsk_sl_expression_member_print (const GskSlExpression *expression,
gsk_sl_printer_append (printer, gsk_sl_type_get_member_name (gsk_sl_expression_get_return_type (member->expr), member->id));
}
static gboolean
gsk_sl_expression_member_is_assignable (const GskSlExpression *expression,
GError **error)
{
const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
return gsk_sl_expression_is_assignable (member->expr, error);
}
static GskSlType *
gsk_sl_expression_member_get_return_type (const GskSlExpression *expression)
{
@@ -867,6 +913,7 @@ gsk_sl_expression_member_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_MEMBER = {
gsk_sl_expression_member_free,
gsk_sl_expression_member_print,
gsk_sl_expression_member_is_assignable,
gsk_sl_expression_member_get_return_type,
gsk_sl_expression_member_get_constant,
gsk_sl_expression_member_write_spv
@@ -918,6 +965,42 @@ gsk_sl_expression_swizzle_print (const GskSlExpression *expression,
}
}
static gboolean
gsk_sl_expression_swizzle_is_assignable (const GskSlExpression *expression,
GError **error)
{
const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
if (!gsk_sl_expression_is_assignable (swizzle->expr, error))
return FALSE;
switch (swizzle->length)
{
default:
g_assert_not_reached ();
case 4:
if (swizzle->indexes[0] == swizzle->indexes[3] ||
swizzle->indexes[1] == swizzle->indexes[3] ||
swizzle->indexes[2] == swizzle->indexes[3])
break;
case 3:
if (swizzle->indexes[0] == swizzle->indexes[2] ||
swizzle->indexes[1] == swizzle->indexes[2])
break;
case 2:
if (swizzle->indexes[0] == swizzle->indexes[1])
break;
case 1:
return TRUE;
}
g_set_error (error,
GSK_SL_COMPILER_ERROR,
GSK_SL_COMPILER_ERROR_SYNTAX,
"Cannot assign to swizzle with duplicate components.");
return FALSE;
}
static GskSlType *
gsk_sl_expression_swizzle_get_return_type (const GskSlExpression *expression)
{
@@ -1022,6 +1105,7 @@ gsk_sl_expression_swizzle_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_SWIZZLE = {
gsk_sl_expression_swizzle_free,
gsk_sl_expression_swizzle_print,
gsk_sl_expression_swizzle_is_assignable,
gsk_sl_expression_swizzle_get_return_type,
gsk_sl_expression_swizzle_get_constant,
gsk_sl_expression_swizzle_write_spv
@@ -1144,6 +1228,7 @@ gsk_sl_expression_negation_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_NEGATION = {
gsk_sl_expression_negation_free,
gsk_sl_expression_negation_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_negation_get_return_type,
gsk_sl_expression_negation_get_constant,
gsk_sl_expression_negation_write_spv
@@ -1206,6 +1291,7 @@ gsk_sl_expression_constant_write_spv (const GskSlExpression *expression,
static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTANT = {
gsk_sl_expression_constant_free,
gsk_sl_expression_constant_print,
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_constant_get_return_type,
gsk_sl_expression_constant_get_constant,
gsk_sl_expression_constant_write_spv
@@ -2331,6 +2417,7 @@ gsk_sl_expression_parse_assignment (GskSlScope *scope,
GskSlExpression *lvalue, *rvalue;
GskSlExpressionAssignment *assign;
GskSlType *result_type;
GError *error = NULL;
lvalue = gsk_sl_expression_parse_conditional (scope, preproc);
@@ -2354,18 +2441,21 @@ gsk_sl_expression_parse_assignment (GskSlScope *scope,
return lvalue;
}
#if 0
if (gsk_sl_expression_is_constant (lvalue))
if (!gsk_sl_expression_is_assignable (lvalue, &error))
{
gsk_sl_preprocessor_error (stream, "Cannot assign to a return lvalue.");
gsk_sl_preprocessor_emit_error (preproc,
TRUE,
gsk_sl_preprocessor_get_location (preproc),
error);
g_clear_error (&error);
/* Continue parsing like normal here to get more errors */
gsk_sl_preprocessor_consume (stream, lvalue);
gsk_sl_preprocessor_consume (preproc, lvalue);
gsk_sl_expression_unref (lvalue);
return gsk_sl_expression_parse_assignment (scope, stream);
return gsk_sl_expression_parse_assignment (scope, preproc);
}
#endif
binary = gsk_sl_binary_get_for_token (token->type);
gsk_sl_preprocessor_consume (preproc, NULL);
@@ -2442,6 +2532,13 @@ gsk_sl_expression_print (const GskSlExpression *expression,
expression->class->print (expression, printer);
}
gboolean
gsk_sl_expression_is_assignable (const GskSlExpression *expression,
GError **error)
{
return expression->class->is_assignable (expression, error);
}
GskSlType *
gsk_sl_expression_get_return_type (const GskSlExpression *expression)
{

View File

@@ -41,6 +41,8 @@ void gsk_sl_expression_unref (GskSlExpression
void gsk_sl_expression_print (const GskSlExpression *expression,
GskSlPrinter *printer);
gboolean gsk_sl_expression_is_assignable (const GskSlExpression *expression,
GError **error);
GskSlType * gsk_sl_expression_get_return_type (const GskSlExpression *expression);
GskSlValue * gsk_sl_expression_get_constant (const GskSlExpression *expression);