-#define TYPE_ANY registry_getanytype()
-#define TYPE_IS_ANY(t) ((t) == registry_getanytype())
-#define TYPE_INT registry_getintclass()
-#define TYPE_IS_INT(t) ((t) == registry_getintclass())
-#define TYPE_UINT registry_getuintclass()
-#define TYPE_IS_UINT(t) ((t) == registry_getuintclass())
-#define TYPE_FLOAT registry_getnumberclass()
-#define TYPE_IS_FLOAT(t) ((t) == registry_getnumberclass())
-#define TYPE_BOOLEAN registry_getbooleanclass()
-#define TYPE_IS_BOOLEAN(t)((t) == registry_getbooleanclass())
-#define TYPE_STRING registry_getstringclass()
-#define TYPE_IS_STRING(t) ((t) == registry_getstringclass())
-#define TYPE_NULL registry_getnullclass()
-#define TYPE_IS_NULL(t) ((t) == registry_getnullclass())
+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;
+}
+