diff --git a/ast.c b/ast.c index ff105cc..fb86b85 100644 --- a/ast.c +++ b/ast.c @@ -570,7 +570,8 @@ ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int fiel self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT); } - self->owner = owner; + self->rvalue = false; + self->owner = owner; ast_propagate_effects(self, owner); self->field = field; @@ -2082,7 +2083,10 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va ir_value *vec; /* in QC this is always an lvalue */ - (void)lvalue; + if (lvalue && self->rvalue) { + compile_error(ast_ctx(self), "not an l-value (member access)"); + return false; + } if (self->expression.outl) { *out = self->expression.outl; return true; diff --git a/ast.h b/ast.h index b9b2ab8..eeba636 100644 --- a/ast.h +++ b/ast.h @@ -324,6 +324,7 @@ struct ast_member_s ast_expression *owner; unsigned int field; const char *name; + bool rvalue; }; ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field, const char *name); void ast_member_delete(ast_member*); diff --git a/parser.c b/parser.c index c780dc2..5aa980d 100644 --- a/parser.c +++ b/parser.c @@ -806,6 +806,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; out = (ast_expression*)ast_member_new(ctx, exprs[1], 0, NULL); out->expression.node.keep = false; + ((ast_member*)out)->rvalue = true; if (vec.x != 1) out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.x), out); } @@ -813,6 +814,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; out = (ast_expression*)ast_member_new(ctx, exprs[1], 1, NULL); out->expression.node.keep = false; + ((ast_member*)out)->rvalue = true; if (vec.y != 1) out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.y), out); } @@ -820,6 +822,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; out = (ast_expression*)ast_member_new(ctx, exprs[1], 2, NULL); out->expression.node.keep = false; + ((ast_member*)out)->rvalue = true; if (vec.z != 1) out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, (ast_expression*)parser_const_float(parser, vec.z), out); } @@ -832,6 +835,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, NULL); out->expression.node.keep = false; + ((ast_member*)out)->rvalue = true; if (vec.x != 1) out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.x)); } @@ -839,6 +843,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; out = (ast_expression*)ast_member_new(ctx, exprs[0], 1, NULL); out->expression.node.keep = false; + ((ast_member*)out)->rvalue = true; if (vec.y != 1) out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.y)); } @@ -846,6 +851,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; out = (ast_expression*)ast_member_new(ctx, exprs[0], 2, NULL); out->expression.node.keep = false; + ((ast_member*)out)->rvalue = true; if (vec.z != 1) out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, out, (ast_expression*)parser_const_float(parser, vec.z)); }