Clean up inplace binary operations for subscripts.
authorLars Knoll <lars.knoll@digia.com>
Sun, 11 Nov 2012 20:56:38 +0000 (21:56 +0100)
committerErik Verbruggen <erik.verbruggen@digia.com>
Mon, 12 Nov 2012 08:17:23 +0000 (09:17 +0100)
Remove a lot of duplicated code, and make it a lot
easier to implement JS compliant semantics.

Change-Id: Ic5ecb58d34a5df8fe05e86c5f906d70c50c51b54
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
qmljs_objects.cpp
qmljs_objects.h
qmljs_runtime.cpp

index 353f7f9..db5e237 100644 (file)
@@ -91,6 +91,13 @@ bool Object::inplaceBinOp(Value rhs, Context *ctx, String *name, BinOp op)
     return true;
 }
 
+bool Object::inplaceBinOp(Value rhs, Value index, BinOp op, Context *ctx)
+{
+    String *name = index.toString(ctx);
+    assert(name);
+    return inplaceBinOp(rhs, ctx, name, op);
+}
+
 // Section 8.12.1
 PropertyDescriptor *Object::__getOwnProperty__(Context *, String *name)
 {
@@ -330,6 +337,18 @@ Value ArrayObject::__get__(Context *ctx, String *name)
     return Object::__get__(ctx, name);
 }
 
+bool ArrayObject::inplaceBinOp(Value rhs, Value index, BinOp op, Context *ctx)
+{
+    if (index.isNumber()) {
+        const quint32 idx = index.toUInt32(ctx);
+        Value v = value.at(idx);
+        v = op(v, rhs, ctx);
+        value.assign(idx, v);
+        return true;
+    }
+    return Object::inplaceBinOp(rhs, index, op, ctx);
+}
+
 bool FunctionObject::hasInstance(Context *ctx, const Value &value)
 {
     if (! value.isObject()) {
index ebb2291..6fae34d 100644 (file)
@@ -413,6 +413,7 @@ struct Object {
 
     Value getValue(Context *ctx, PropertyDescriptor *p) const;
     bool inplaceBinOp(Value rhs, Context *ctx, String *name, BinOp op);
+    virtual bool inplaceBinOp(Value rhs, Value index, BinOp op, Context *ctx);
 };
 
 struct ForEachIteratorObject: Object {
@@ -460,6 +461,8 @@ struct ArrayObject: Object {
     virtual QString className() { return QStringLiteral("Array"); }
     virtual ArrayObject *asArrayObject() { return this; }
     virtual Value __get__(Context *ctx, String *name);
+
+    virtual bool inplaceBinOp(Value rhs, Value index, BinOp op, Context *ctx);
 };
 
 struct FunctionObject: Object {
index e98b7eb..4821b45 100644 (file)
@@ -555,188 +555,67 @@ void __qmljs_inplace_ushr_name(Value value, String *name, Context *ctx)
 void __qmljs_inplace_bit_and_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_bit_and(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_bit_and);
+    obj->inplaceBinOp(value, index, __qmljs_bit_and, ctx);
 }
 
 void __qmljs_inplace_bit_or_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_bit_or(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_bit_or);
+    obj->inplaceBinOp(value, index, __qmljs_bit_or, ctx);
 }
 
 void __qmljs_inplace_bit_xor_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_bit_xor(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_bit_xor);
+    obj->inplaceBinOp(value, index, __qmljs_bit_xor, ctx);
 }
 
 void __qmljs_inplace_add_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_add(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_add);
+    obj->inplaceBinOp(value, index, __qmljs_add, ctx);
 }
 
 void __qmljs_inplace_sub_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_sub(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_sub);
+    obj->inplaceBinOp(value, index, __qmljs_sub, ctx);
 }
 
 void __qmljs_inplace_mul_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_mul(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_mul);
+    obj->inplaceBinOp(value, index, __qmljs_mul, ctx);
 }
 
 void __qmljs_inplace_div_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_div(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_div);
+    obj->inplaceBinOp(value, index, __qmljs_div, ctx);
 }
 
 void __qmljs_inplace_mod_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_mod(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_mod);
+    obj->inplaceBinOp(value, index, __qmljs_mod, ctx);
 }
 
 void __qmljs_inplace_shl_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_shl(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_shl);
+    obj->inplaceBinOp(value, index, __qmljs_shl, ctx);
 }
 
 void __qmljs_inplace_shr_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_shr(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_shr);
+    obj->inplaceBinOp(value, index, __qmljs_shr, ctx);
 }
 
 void __qmljs_inplace_ushr_element(Value base, Value index, Value value, Context *ctx)
 {
     Object *obj = base.toObject(ctx).objectValue();
-    if (ArrayObject *a = obj->asArrayObject()) {
-        if (index.isNumber()) {
-            const quint32 idx = index.toUInt32(ctx);
-            Value v = a->value.at(idx);
-            v = __qmljs_ushr(v, value, ctx);
-            a->value.assign(idx, v);
-            return;
-        }
-    }
-    String *name = index.toString(ctx);
-    assert(name);
-    obj->inplaceBinOp(value, ctx, name, __qmljs_ushr);
+    obj->inplaceBinOp(value, index, __qmljs_ushr, ctx);
 }
 
 void __qmljs_inplace_bit_and_member(Value value, Value base, String *name, Context *ctx)