%token<token> T_GE ">="
%token<token> T_DIVBY "/="
%token<token> T_MODBY "%="
+%token<token> T_MULBY "*="
%token<token> T_PLUSBY "+="
%token<token> T_MINUSBY "-="
%token<token> T_SHRBY ">>="
%left prec_none
%right '?' ':'
-%nonassoc '='
-%nonassoc "/=" "%="
-%nonassoc "+=" "-="
-%nonassoc ">>="
-%nonassoc "<<="
-%nonassoc ">>>="
+%right '=' "/=" "%=" "*=" "+=" "-=" ">>=" "<<=" ">>>="
%left "||"
%left "&&"
%nonassoc '|'
abc_method_body_t*m;
dict_t*vars;
- int local_var_base;
char late_binding;
} state_t;
memcpy(s, state, sizeof(state_t)); //shallow copy
sl->next = state_stack;
sl->state = s;
- if(oldstate) {
- s->local_var_base = oldstate->vars->num + oldstate->local_var_base;
- }
if(!s->imports) {
s->imports = dict_new();
}
code_t* killvars(code_t*c)
{
int t;
- for(t=0;t<state->vars->num;t++) {
- //do this always, otherwise register types don't match
- //in the verifier when doing nested loops
- //if(!TYPE_IS_BUILTIN_SIMPLE(type)) {
- c = abc_kill(c, t+state->local_var_base);
- //}
+ for(t=0;t<state->vars->hashsize;t++) {
+ dictentry_t*e =state->vars->slots[t];
+ while(e) {
+ variable_t*v = (variable_t*)e->data;
+ //do this always, otherwise register types don't match
+ //in the verifier when doing nested loops
+ //if(!TYPE_IS_BUILTIN_SIMPLE(type)) {
+ c = abc_kill(c, v->index);
+ e = e->next;
+ }
}
return c;
}
if(!b) syntaxerror("internal error: assertion failed");
}
-static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign)
+static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore)
{
/* converts this:
prefix = 0;
}
- int use_temp_var = 0;
+ char use_temp_var = readbefore;
/* generate the write instruction, and maybe append a dup to the prefix code */
code_t* write = abc_nop(0);
if(m->type != QNAME)
syntaxerror("illegal lvalue: can't assign a value to this expression (not a qname)");
if(!justassign) {
- prefix = abc_dup(prefix); // we need the object, too
use_temp_var = 1;
+ prefix = abc_dup(prefix); // we need the object, too
}
} else if(r->opcode == OPCODE_GETSLOT) {
write->opcode = OPCODE_SETSLOT;
write->data[0] = r->data[0];
if(!justassign) {
- prefix = abc_dup(prefix); // we need the object, too
use_temp_var = 1;
+ prefix = abc_dup(prefix); // we need the object, too
}
} else if(r->opcode == OPCODE_GETLOCAL) {
write->opcode = OPCODE_SETLOCAL;
temp = gettempvar();
c = code_append(c, prefix);
c = code_append(c, r);
+ if(readbefore) {
+ c = abc_dup(c);
+ c = abc_setlocal(c, temp);
+ }
c = code_append(c, middlepart);
- c = abc_dup(c);
- c = abc_setlocal(c, temp);
+ if(!readbefore) {
+ c = abc_dup(c);
+ c = abc_setlocal(c, temp);
+ }
c = code_append(c, write);
c = abc_getlocal(c, temp);
c = abc_kill(c, temp);
} else {
- /* if we're allowed to execute the read code twice, things
- are easier */
+ /* if we're allowed to execute the read code twice *and*
+ the middlepart doesn't modify the code, things are easier.
+ */
code_t* r2 = code_dup(r);
//c = code_append(c, prefix);
parserassert(!prefix);
$$.c = abc_getproperty2($$.c, &m);
}
+E : E "*=" E {
+ code_t*c = $3.c;
+ if(TYPE_IS_INT($3.t) || TYPE_IS_UINT($3.t)) {
+ c=abc_multiply_i(c);
+ } else {
+ c=abc_multiply(c);
+ }
+ c=converttype(c, join_types($1.t, $3.t, '*'), $1.t);
+ $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.t = $1.t;
+ }
+E : E "%=" E {
+ code_t*c = abc_modulo($3.c);
+ c=converttype(c, join_types($1.t, $3.t, '%'), $1.t);
+ $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.t = $1.t;
+ }
+E : E "<<=" E {
+ code_t*c = abc_lshift($3.c);
+ c=converttype(c, join_types($1.t, $3.t, '<'), $1.t);
+ $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.t = $1.t;
+ }
+E : E ">>=" E {
+ code_t*c = abc_rshift($3.c);
+ c=converttype(c, join_types($1.t, $3.t, '>'), $1.t);
+ $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.t = $1.t;
+ }
+E : E ">>>=" E {
+ code_t*c = abc_urshift($3.c);
+ c=converttype(c, join_types($1.t, $3.t, 'U'), $1.t);
+ $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.t = $1.t;
+ }
+E : E "/=" E {
+ code_t*c = abc_divide($3.c);
+ c=converttype(c, join_types($1.t, $3.t, '/'), $1.t);
+ $$.c = toreadwrite($1.c, c, 0, 0);
+ $$.t = $1.t;
+ }
E : E "+=" E {
code_t*c = $3.c;
if(TYPE_IS_INT($3.t) || TYPE_IS_UINT($3.t)) {
}
c=converttype(c, join_types($1.t, $3.t, '+'), $1.t);
- $$.c = toreadwrite($1.c, c, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0);
$$.t = $1.t;
}
E : E "-=" E { code_t*c = $3.c;
}
c=converttype(c, join_types($1.t, $3.t, '-'), $1.t);
- $$.c = toreadwrite($1.c, c, 0);
+ $$.c = toreadwrite($1.c, c, 0, 0);
$$.t = $1.t;
}
E : E '=' E { code_t*c = 0;
c = code_append(c, $3.c);
c = converttype(c, $3.t, $1.t);
- $$.c = toreadwrite($1.c, c, 1);
+ $$.c = toreadwrite($1.c, c, 1, 0);
$$.t = $1.t;
}
type = TYPE_NUMBER;
}
c=converttype(c, type, $1.t);
- $$.c = toreadwrite($1.c, c, 0);
+ $$.c = toreadwrite($1.c, c, 0, 1);
$$.t = $1.t;
}
E : E "--" { code_t*c = 0;
classinfo_t*type = $1.t;
if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
- c=abc_increment_i(c);
+ c=abc_decrement_i(c);
} else {
- c=abc_increment(c);
+ c=abc_decrement(c);
type = TYPE_NUMBER;
}
c=converttype(c, type, $1.t);
- $$.c = toreadwrite($1.c, c, 0);
+ $$.c = toreadwrite($1.c, c, 0, 1);
$$.t = $1.t;
}
+E : "++" E { code_t*c = 0;
+ classinfo_t*type = $2.t;
+ if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
+ c=abc_increment_i(c);
+ } else {
+ c=abc_increment(c);
+ type = TYPE_NUMBER;
+ }
+ c=converttype(c, type, $2.t);
+ $$.c = toreadwrite($2.c, c, 0, 0);
+ $$.t = $2.t;
+ }
+
+E : "--" E { code_t*c = 0;
+ classinfo_t*type = $2.t;
+ if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
+ c=abc_decrement_i(c);
+ } else {
+ c=abc_decrement(c);
+ type = TYPE_NUMBER;
+ }
+ c=converttype(c, type, $2.t);
+ $$.c = toreadwrite($2.c, c, 0, 0);
+ $$.t = $2.t;
+ }
+
E : E '.' T_IDENTIFIER
{$$.c = $1.c;
if($$.t) {