+ if(!b) syntaxerror("internal error: assertion failed");
+}
+
+static classinfo_t* find_class(char*name)
+{
+ classinfo_t*c=0;
+
+ c = registry_findclass(state->package, name);
+
+ /* try explicit imports */
+ dictentry_t* e = dict_get_slot(state->imports, name);
+ while(e) {
+ if(c)
+ break;
+ if(!strcmp(e->key, name)) {
+ c = (classinfo_t*)e->data;
+ }
+ e = e->next;
+ }
+
+ /* try package.* imports */
+ import_list_t*l = state->wildcard_imports;
+ while(l) {
+ if(c)
+ break;
+ //printf("does package %s contain a class %s?\n", l->import->package, name);
+ c = registry_findclass(l->import->package, name);
+ l = l->next;
+ }
+
+ /* try global package */
+ if(!c) {
+ c = registry_findclass("", name);
+ }
+ return c;
+}
+
+static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore)
+{
+ /* converts this:
+
+ [prefix code] [read instruction]
+
+ to this:
+
+ [prefix code] ([dup]) [read instruction] [middlepart] [setvar] [write instruction] [getvar]
+ */
+
+ if(in && in->opcode == OPCODE_COERCE_A) {
+ in = code_cutlast(in);
+ }
+ if(in->next)
+ syntaxerror("internal error");
+
+ /* chop off read instruction */
+ code_t*prefix = in;
+ code_t*r = in;
+ if(r->prev) {
+ prefix = r->prev;r->prev = 0;
+ prefix->next=0;
+ } else {
+ prefix = 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(r->opcode == OPCODE_GETPROPERTY) {
+ write->opcode = OPCODE_SETPROPERTY;
+ multiname_t*m = (multiname_t*)r->data[0];
+ write->data[0] = multiname_clone(m);
+ if(m->type != QNAME && m->type != MULTINAME)
+ 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;
+ } 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;
+ } else if(r->opcode == OPCODE_GETLOCAL) {
+ write->opcode = OPCODE_SETLOCAL;
+ write->data[0] = r->data[0];
+ } else if(r->opcode == OPCODE_GETLOCAL_0) {
+ write->opcode = OPCODE_SETLOCAL_0;
+ } else if(r->opcode == OPCODE_GETLOCAL_1) {
+ write->opcode = OPCODE_SETLOCAL_1;
+ } else if(r->opcode == OPCODE_GETLOCAL_2) {
+ write->opcode = OPCODE_SETLOCAL_2;
+ } else if(r->opcode == OPCODE_GETLOCAL_3) {
+ write->opcode = OPCODE_SETLOCAL_3;
+ } else {
+ code_dump(r, 0, 0, "", stdout);
+ syntaxerror("illegal lvalue: can't assign a value to this expression");
+ }
+ code_t* c = 0;
+
+ int temp = -1;
+ if(!justassign) {
+ if(use_temp_var) {
+ /* with getproperty/getslot, we have to be extra careful not
+ to execute the read code twice, as it might have side-effects
+ (e.g. if the property is in fact a setter/getter combination)
+
+ So read the value, modify it, and write it again,
+ using prefix only once and making sure (by using a temporary
+ register) that the return value is what we just wrote */
+ 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);
+ 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 *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 = code_append(c, r);
+ c = code_append(c, middlepart);
+ c = code_append(c, write);
+ c = code_append(c, r2);
+ }
+ } else {
+ /* even smaller version: overwrite the value without reading
+ it out first */
+ if(!use_temp_var) {
+ if(prefix) {
+ c = code_append(c, prefix);
+ c = abc_dup(c);
+ }
+ c = code_append(c, middlepart);
+ c = code_append(c, write);
+ c = code_append(c, r);
+ } else {
+ temp = gettempvar();
+ if(prefix) {
+ c = code_append(c, prefix);
+ c = abc_dup(c);
+ }
+ c = code_append(c, middlepart);
+ c = abc_dup(c);
+ c = abc_setlocal(c, temp);
+ c = code_append(c, write);
+ c = abc_getlocal(c, temp);
+ }
+ }
+
+ return c;