Re: Array rvals, lvals and dimension
David Hakim <dhakim-Gkm/TONP9n1Wk0Htik3J/[email protected]> Wed, 30 Apr 2003 22:41:53 -0400
| Newsgroups | gmane.comp.lang.moto.devel |
|---|---|
| Message-ID | <[email protected]> |
On Wednesday, April 30, 2003, at 08:27 PM, Stefano Corsi wrote:
> Dave,
>
> I have modified array_rval and array_lval in motov.c and motoc.c to
> reflect
> the way they are called in motoi.c, as you suggested. All tests pass
> and the
> change seems to work fine.
>
> Then I did something strange: I noticed that the for loop for all
> dimensions
> in motoi_array_lval is never executed more than once.
Yep, looks like moto.y changed to a recursive rule for subscripts a
while back
array_subscript_expression
: postfix_expression array_index {$$=op(ENV,
ARRAY_RVAL,UCMetaInfo($1),2,$1,$2);}
;
It grabs one index at a time instead of constructing an
array_index_list for ARRAY_RVAL and ARRAY_LVAL ops.
> So I did some (dumb
> monkey style) cutting job and I resized the motoi_array_lval to just
> evaluate ONE array index without the for loop, and, quite
> unexpectedly, it
> works and passes all tests.
:)
> Can you see some side effects in the cutting job I did and maybe
> produce a
> test to show it?
> Here is the moto_array_lval after my work. If it's good, then
> implementing the
> [] overl. operator could be a bit nearer.
>
> motoi_array_lval(const UnionCell *p){
> MotoEnv *env = moto_getEnv();
> MotoVal *val, *ival;
> MotoVar *rvar;
> UnArray *ua;
> int *dimarr;
>
> /* Evaluate the first operand to get the Array*/
> motoi(uc_operand(p, 0));
> val = opstack_pop(env);
>
> /* Evaluate the ARRAY_INDEX element */
> motoi(uc_operand(p, 1)); /* array_index list */
> ival = opstack_pop(env);
>
right ... it looks like it hasn't been an array_index_list for some
time ... good thing too :)
> /* Build an array of the specified indexes */
> dimarr = (int*)emalloc(sizeof(int)* (1));
>
Do we even need to bother with dimarr anymore ? Since we are only
subscripting one index at a time I think we can lose it and just store
a local 'index' value. That will save us from having to clean up the
memory later and speed up the interpreter in cases when the number of
array accesses is high.
> if (ival->type->kind == INT32_TYPE)
> dimarr[0] = iv(ival);
> else /* (ival->type->kind == INT64_TYPE) */
> dimarr[0] = lv(ival);
> moto_freeVal(env,ival);
>
> rvar = moto_createVar(
> env,NULL,
> val->type->atype->name,
> val->type->dim - 1,
> '\1',
> NULL
> );
>
> /* Clean up val now since we might need to throw an exception */
> moto_freeVal(env,val);
>
> if (ua == NULL){
> /* Clean up and throw NullPointerException */
> free(dimarr);
> moto_freeVar(env,rvar);
> MOTO_THROW("NullPointerException","Attempt to subscript null");
> }
> if(dimarr[0] < 0 || dimarr[0] >= ua->meta.length){
> /* Clean up and throw ArrayBoundsException */
> free(dimarr);
> moto_freeVar(env,rvar);
> MOTO_THROW("ArrayBoundsException","Attempt to subscript array
> outside
> of declared bounds");
> }
>
> if (val->type->dim == 1){
> switch (val->type->atype->kind){
> case INT32_TYPE: rvar->address = &ua->ia.data[dimarr[0]];
> break;
> case INT64_TYPE: rvar->address = &ua->la.data[dimarr[0]];
> break;
> case FLOAT_TYPE: rvar->address = &ua->fa.data[dimarr[0]];
> break;
> case DOUBLE_TYPE: rvar->address = &ua->da.data[dimarr[0]];
> break;
> case BOOLEAN_TYPE: rvar->address =
> &ua->ba.data[dimarr[0]]; break;
> case BYTE_TYPE: rvar->address = &ua->ya.data[dimarr[0]];
> break;
> case CHAR_TYPE: rvar->address = &ua->ca.data[dimarr[0]];
> break;
> case REF_TYPE: rvar->address = &ua->ra.data[dimarr[0]];
> break;
> default: {THROW_D("MotoCellTypeException");}
> }
> } else {
> rvar->address = &ua->aa.data[dimarr[0]];
> }
>
> free(dimarr);
> opstack_push(env, (MotoVal*)rvar);
> }
>
>
Looks good to me!
-Dave