From a78cdd5366168e2cb4c97deee0ef4eab1c6bdccf Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Sun, 11 Nov 2012 21:27:02 +0100 Subject: [PATCH] calling the array setter when required --- ast.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/ast.c b/ast.c index ac204d3..a134be2 100644 --- a/ast.c +++ b/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 -- 2.39.2