mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-19 14:50:48 +00:00
calling the array setter when required
This commit is contained in:
parent
feec2d74ee
commit
a78cdd5366
1 changed files with 68 additions and 12 deletions
80
ast.c
80
ast.c
|
@ -1244,6 +1244,10 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
|
|||
ast_expression_codegen *cgen;
|
||||
ir_value *left, *right;
|
||||
|
||||
ast_array_index *ai;
|
||||
ast_value *arr;
|
||||
ast_value *idx;
|
||||
|
||||
if (lvalue && self->expression.outl) {
|
||||
*out = self->expression.outl;
|
||||
return true;
|
||||
|
@ -1254,20 +1258,72 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
|
|||
return true;
|
||||
}
|
||||
|
||||
cgen = self->dest->expression.codegen;
|
||||
/* lvalue! */
|
||||
if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
|
||||
return false;
|
||||
self->expression.outl = left;
|
||||
if (ast_istype(self->dest, ast_array_index))
|
||||
{
|
||||
|
||||
cgen = self->source->expression.codegen;
|
||||
/* rvalue! */
|
||||
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
||||
return false;
|
||||
ai = (ast_array_index*)self->dest;
|
||||
idx = (ast_value*)ai->index;
|
||||
|
||||
if (!ir_block_create_store_op(func->curblock, self->op, left, right))
|
||||
return false;
|
||||
self->expression.outr = right;
|
||||
if (ast_istype(ai->index, ast_value) && idx->isconst)
|
||||
ai = NULL;
|
||||
}
|
||||
|
||||
if (ai) {
|
||||
/* we need to call the setter */
|
||||
ir_value *iridx, *funval;
|
||||
ir_instr *call;
|
||||
|
||||
if (lvalue) {
|
||||
asterror(ast_ctx(self), "array-subscript assignment cannot produce lvalues");
|
||||
return false;
|
||||
}
|
||||
|
||||
arr = (ast_value*)ai->array;
|
||||
if (!ast_istype(ai->array, ast_value) || !arr->setter) {
|
||||
asterror(ast_ctx(self), "value has no setter (%s)", arr->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
cgen = idx->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(idx), func, false, &iridx))
|
||||
return false;
|
||||
|
||||
cgen = arr->setter->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval))
|
||||
return false;
|
||||
|
||||
cgen = self->source->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
||||
return false;
|
||||
|
||||
call = ir_block_create_call(func->curblock, ast_function_label(func, "store"), funval);
|
||||
if (!call)
|
||||
return false;
|
||||
if (!ir_call_param(call, iridx))
|
||||
return false;
|
||||
if (!ir_call_param(call, right))
|
||||
return false;
|
||||
self->expression.outr = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* regular code */
|
||||
|
||||
cgen = self->dest->expression.codegen;
|
||||
/* lvalue! */
|
||||
if (!(*cgen)((ast_expression*)(self->dest), func, true, &left))
|
||||
return false;
|
||||
self->expression.outl = left;
|
||||
|
||||
cgen = self->source->expression.codegen;
|
||||
/* rvalue! */
|
||||
if (!(*cgen)((ast_expression*)(self->source), func, false, &right))
|
||||
return false;
|
||||
|
||||
if (!ir_block_create_store_op(func->curblock, self->op, left, right))
|
||||
return false;
|
||||
self->expression.outr = right;
|
||||
}
|
||||
|
||||
/* Theoretically, an assinment returns its left side as an
|
||||
* lvalue, if we don't need an lvalue though, we return
|
||||
|
|
Loading…
Reference in a new issue