X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fexpr.c;h=c07478b6066370fcf2978f56a92164135b7e0f94;hb=4dacf8e5890fb8cd0f53afbd4305c8b9ff9e7986;hp=60c08bccea0056fc6b386ce38704fb15c8cd8287;hpb=3dea7306ae2c9590673c10dec1fbabcd6d7e1806;p=swftools.git diff --git a/lib/as3/expr.c b/lib/as3/expr.c index 60c08bc..c07478b 100644 --- a/lib/as3/expr.c +++ b/lib/as3/expr.c @@ -65,10 +65,27 @@ static classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, nodetype_t*t) { - if(!type1 || !type2) - return TYPE_ANY; - if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2)) - return TYPE_ANY; + if(t == &node_plus) { + if((TYPE_IS_XMLLIST(type1) || TYPE_IS_XML(type1)) && + (TYPE_IS_XMLLIST(type2) || TYPE_IS_XML(type2))) + return TYPE_OBJECT; + if(BOTH_INT(type1, type2)) + return TYPE_INT; + if(IS_NUMBER_OR_INT(type1) && IS_NUMBER_OR_INT(type2)) + return TYPE_NUMBER; + if(TYPE_IS_DATE(type1) || TYPE_IS_DATE(type2)) + return TYPE_OBJECT; + if(TYPE_IS_STRING(type1) || TYPE_IS_STRING(type2)) { + /* depending on where the strings come from, the result type + of an "add" might be an object or a string, depending on the + verifier's mood. So basically we just don't know the type. */ + return TYPE_VOID; + } + if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2)) + return TYPE_ANY; + return TYPE_OBJECT; // e.g. array+array = object + } + if(type1 == type2) return type1; return TYPE_ANY; @@ -132,7 +149,8 @@ static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char r 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) { + if(m->type == QNAME || m->type == MULTINAME || + m->type == QNAMEA || m->type == MULTINAMEA) { if(!justassign) { prefix = abc_dup(prefix); // we need the object, too } @@ -317,7 +335,6 @@ constant_t node_plus_eval(node_t*n) EVAL_HEADER_LEFTRIGHT; char left_int = left.type == CONSTANT_INT || left.type == CONSTANT_UINT; if(left_int && (right.type == CONSTANT_INT || right.type == CONSTANT_UINT)) { - /* FIXME: what to do about signed/unsigned overflows? */ int i = constant_to_int(&left) + constant_to_int(&right); r.type = CONSTANT_INT; r.i = i; @@ -337,6 +354,7 @@ constant_t node_plus_eval(node_t*n) r.s = malloc(sizeof(string_t)); r.s->str = s; r.s->len = l1+l2; + free(add); } else { r.type = CONSTANT_UNKNOWN; } @@ -1464,7 +1482,11 @@ typedcode_t node_as_read(node_t*n) READ_HEADER_LEFTRIGHT; c = code_append(left.c, right.c); c = abc_astypelate(c); - t = TYPE_ANY; + if(TYPE_IS_CLASS(right.t) && right.t->data) { + t = (classinfo_t*)right.t->data; + } else { + t = TYPE_ANY; + } RET; } code_t* node_as_exec(node_t*n) @@ -2053,7 +2075,7 @@ typedcode_t node_pluseq_read(node_t*n) c = abc_add_i(c); } else { c = abc_add(c); - c = converttype(c, TYPE_NUMBER, left.t); + c = converttype(c, join_types(left.t,right.t,&node_plus), left.t); } c = toreadwrite(left.c, c, 0, 0, 1); t = left.t; @@ -2067,7 +2089,7 @@ code_t* node_pluseq_exec(node_t*n) c = abc_add_i(c); } else { c = abc_add(c); - c = converttype(c, TYPE_NUMBER, left.t); + c = converttype(c, join_types(left.t,right.t,&node_plus), left.t); } return toreadwrite(left.c, c, 0, 0, 0); } @@ -2563,7 +2585,12 @@ typedcode_t node_const_read(node_t*n) case CONSTANT_NAMESPACE_PRIVATE: c = abc_pushnamespace(0, v->ns); break; - default: syntaxerror("invalid constant"); + case CONSTANT_UNKNOWN: + syntaxerror("internal error: invalid constant"); + default: + *(int*)0=0; + syntaxerror("invalid constant (%d)", v->type); + } RET; } @@ -2597,9 +2624,9 @@ typedcode_t node_code_write(node_t*n) } typedcode_t node_code_read(node_t*n) { - /* TODO: this dup might be unnecessary- n->code.c is only read out once */ typedcode_t t; - t.c = code_dup(n->code.c); + t.c = n->code.c; + n->code.c=0; t.t = n->code.t; return t; } @@ -2744,13 +2771,13 @@ node_t* mknode3(nodetype_t*t, node_t*one, node_t*two, node_t*three) void node_free(node_t*n) { int t; - if(n->type == &node_const) { - constant_free(n->value);n->value = 0; - } - else if(n->type == &node_code) { - code_free(n->code.c);n->code.c = 0; - } - else for(t=0;tnum_children;t++) { + if(n->type == &node_code) { + if(n->code.c) { + code_free(n->code.c);n->code.c = 0; + } + } else if(n->type == &node_const) { + /* keep, this is not our reference */ + } else for(t=0;tnum_children;t++) { node_free(n->child[t]);n->child[t] = 0; } free(n); @@ -2812,7 +2839,7 @@ void node_dump2(node_t*n, const char*p1, const char*p2, FILE*fi) fprintf(fi, "%s%s (%s)\n", p1, n->type->name, s); free(s); } else if(n->type == &node_code) { - fprintf(fi, "%s%s\n", p1, n->type->name); + fprintf(fi, "%s%s (%s)\n", p1, n->type->name, n->code.t?n->code.t->name:"*"); code_dump2(n->code.c, 0, 0, (char*)p2, fi); } else { fprintf(fi, "%s%s\n", p1, n->type->name); @@ -2821,8 +2848,8 @@ void node_dump2(node_t*n, const char*p1, const char*p2, FILE*fi) void node_dump(node_t*n) { - printf("---------------------------VVVV\n"); + printf("------------VVVV---------------\n"); node_dump2(n,"","",stdout); - printf("---------------------------^^^^\n"); + printf("-------------------------------\n"); }