+static int find_variable(char*name, classinfo_t**m)
+{
+ state_list_t* s = state_stack;
+ while(s) {
+ int i = array_find(s->state->vars, name);
+ if(i>=0) {
+ if(m) {
+ *m = array_getvalue(s->state->vars, i);
+ }
+ return i + s->state->local_var_base;
+ }
+ s = s->next;
+ }
+ return -1;
+}
+static int find_variable_safe(char*name, classinfo_t**m)
+{
+ int i = find_variable(name, m);
+ if(i<0)
+ syntaxerror("undefined variable: %s", name);
+ return i;
+}
+static char variable_exists(char*name)
+{
+ return array_contains(state->vars, name);
+}
+static int new_variable(char*name, classinfo_t*type)
+{
+ return array_append(state->vars, name, type) + state->local_var_base;
+}
+#define TEMPVARNAME "__as3_temp__"
+static int gettempvar()
+{
+ int i = find_variable(TEMPVARNAME, 0);
+ if(i<0) {
+ return new_variable(TEMPVARNAME, 0);
+ } else {
+ return i;
+ }
+}
+
+code_t* killvars(code_t*c)
+{
+ int t;
+ for(t=0;t<state->vars->num;t++) {
+ classinfo_t*type = array_getvalue(state->vars, 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);
+ //}
+ }
+ return c;
+}
+
+char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
+{
+ return 1; // FIXME
+}
+
+void breakjumpsto(code_t*c, code_t*jump)
+{
+ while(c->prev)
+ c=c->prev;
+ while(c) {
+ if(c->opcode == OPCODE___BREAK__) {
+ c->opcode = OPCODE_JUMP;
+ c->branch = jump;
+ }
+ c = c->next;
+ }
+}
+
+classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, char op)
+{
+ return registry_getanytype(); // FIXME
+}
+code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
+{
+ if(from==to)
+ return c;
+ if(!to) {
+ /*TODO: can omit this if from is zero? */
+ return abc_coerce_a(c);
+ }
+ if(TYPE_IS_NUMBER(from) && TYPE_IS_UINT(to)) {
+ MULTINAME(m, TYPE_UINT);
+ return abc_coerce2(c, &m);
+ }
+ if(TYPE_IS_NUMBER(from) && TYPE_IS_INT(to)) {
+ MULTINAME(m, TYPE_INT);
+ return abc_coerce2(c, &m);
+ }
+ return c;
+}
+
+code_t*defaultvalue(code_t*c, classinfo_t*type)
+{
+ if(TYPE_IS_INT(type) || TYPE_IS_UINT(type) || TYPE_IS_FLOAT(type)) {
+ c = abc_pushbyte(c, 0);
+ } else if(TYPE_IS_BOOLEAN(type)) {
+ c = abc_pushfalse(c);
+ } else {
+ c = abc_pushnull(c);
+ }
+ return c;
+}
+
+char is_pushundefined(code_t*c)
+{
+ return (c && !c->prev && !c->next && c->opcode == OPCODE_PUSHUNDEFINED);
+}
+
+static code_t* toreadwrite(code_t*in, code_t*middlepart)
+{
+ /* converts this:
+
+ [prefix code] [read instruction]
+
+ to this:
+
+ [prefix code] ([dup]) [read instruction] [setvar] [middlepart] [write instruction] [getvar]
+ */
+
+ if(in->next)
+ syntaxerror("internal error");
+
+ int temp = gettempvar();
+
+ /* 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;
+ }
+
+ /* generate the write instruction, and maybe append a dup to the prefix code */
+ code_t* write = abc_nop(middlepart);
+ 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)
+ syntaxerror("illegal lvalue: can't assign a value to this expression (not a qname)");
+ 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];
+ prefix = abc_dup(prefix); // we need the object, too
+ } 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 = prefix;
+ c = code_append(c, r);
+
+ c = abc_dup(c);
+ c = abc_setlocal(c, temp);
+ c = code_append(c, middlepart);
+ c = abc_getlocal(c, temp);
+ c = abc_kill(c, temp);
+
+ return c;
+}
+
+