Improve handling of binops on LHS expressions
Add a generic method to handle binops such as += to Object and use it. We can probably remove most of the __qmljs_inplace_xxx methods later on and call one generic method instead. Change-Id: If7cbd2e3012ad381e29b9eec2059e17f02a0a38a Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
parent
d5fe0946bd
commit
0c1424362f
|
|
@ -69,6 +69,28 @@ void Object::__put__(Context *ctx, const QString &name, void (*code)(Context *),
|
|||
__put__(ctx, name, Value::fromObject(ctx->engine->newNativeFunction(ctx, code)));
|
||||
}
|
||||
|
||||
Value Object::getValue(Context *ctx, PropertyDescriptor *p) const
|
||||
{
|
||||
if (p->isData())
|
||||
return p->value;
|
||||
if (!p->get)
|
||||
return Value::undefinedValue();
|
||||
|
||||
p->get->call(ctx, Value::fromObject(const_cast<Object *>(this)), 0, 0);
|
||||
return ctx->result;
|
||||
}
|
||||
|
||||
bool Object::inplaceBinOp(Value rhs, Context *ctx, String *name, BinOp op)
|
||||
{
|
||||
PropertyDescriptor to_fill;
|
||||
PropertyDescriptor *pd = __getPropertyDescriptor__(ctx, name, &to_fill);
|
||||
if (!pd)
|
||||
return false;
|
||||
Value result = op(getValue(ctx, pd), rhs, ctx);
|
||||
__put__(ctx, name, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Section 8.12.1
|
||||
PropertyDescriptor *Object::__getOwnProperty__(Context *, String *name)
|
||||
{
|
||||
|
|
@ -95,17 +117,9 @@ Value Object::__get__(Context *ctx, String *name)
|
|||
return Value::fromObject(prototype);
|
||||
|
||||
PropertyDescriptor tmp;
|
||||
if (PropertyDescriptor *p = __getPropertyDescriptor__(ctx, name, &tmp)) {
|
||||
if (p->isData())
|
||||
return p->value;
|
||||
if (!p->get)
|
||||
return Value::undefinedValue();
|
||||
FunctionObject *f = p->get->asFunctionObject();
|
||||
if (f) {
|
||||
f->call(ctx, Value::fromObject(this), 0, 0);
|
||||
return ctx->result;
|
||||
}
|
||||
}
|
||||
if (PropertyDescriptor *p = __getPropertyDescriptor__(ctx, name, &tmp))
|
||||
return getValue(ctx, p);
|
||||
|
||||
return Value::undefinedValue();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -410,6 +410,9 @@ struct Object {
|
|||
//
|
||||
void __put__(Context *ctx, const QString &name, const Value &value);
|
||||
void __put__(Context *ctx, const QString &name, void (*code)(Context *), int count = 0);
|
||||
|
||||
Value getValue(Context *ctx, PropertyDescriptor *p) const;
|
||||
bool inplaceBinOp(Value rhs, Context *ctx, String *name, BinOp op);
|
||||
};
|
||||
|
||||
struct ForEachIteratorObject: Object {
|
||||
|
|
|
|||
|
|
@ -597,9 +597,9 @@ void __qmljs_inplace_bit_and_element(Value base, Value index, Value value, Conte
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_bit_and_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_bit_and);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_bit_or_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -614,9 +614,9 @@ void __qmljs_inplace_bit_or_element(Value base, Value index, Value value, Contex
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_bit_or_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_bit_or);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_bit_xor_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -631,9 +631,9 @@ void __qmljs_inplace_bit_xor_element(Value base, Value index, Value value, Conte
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_bit_xor_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_bit_xor);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_add_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -648,9 +648,9 @@ void __qmljs_inplace_add_element(Value base, Value index, Value value, Context *
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_add_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_add);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_sub_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -665,9 +665,9 @@ void __qmljs_inplace_sub_element(Value base, Value index, Value value, Context *
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_sub_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_sub);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_mul_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -682,9 +682,9 @@ void __qmljs_inplace_mul_element(Value base, Value index, Value value, Context *
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_mul_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_mul);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_div_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -699,9 +699,9 @@ void __qmljs_inplace_div_element(Value base, Value index, Value value, Context *
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_div_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_div);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_mod_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -716,9 +716,9 @@ void __qmljs_inplace_mod_element(Value base, Value index, Value value, Context *
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_mod_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_mod);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_shl_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -733,9 +733,9 @@ void __qmljs_inplace_shl_element(Value base, Value index, Value value, Context *
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_shl_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_shl);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_shr_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -750,9 +750,9 @@ void __qmljs_inplace_shr_element(Value base, Value index, Value value, Context *
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_shr_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_shr);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_ushr_element(Value base, Value index, Value value, Context *ctx)
|
||||
|
|
@ -767,97 +767,75 @@ void __qmljs_inplace_ushr_element(Value base, Value index, Value value, Context
|
|||
return;
|
||||
}
|
||||
}
|
||||
String *s = index.toString(ctx);
|
||||
assert(s);
|
||||
__qmljs_inplace_ushr_member(value, base, s, ctx);
|
||||
String *name = index.toString(ctx);
|
||||
assert(name);
|
||||
obj->inplaceBinOp(value, ctx, name, __qmljs_ushr);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_bit_and_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_bit_and(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_bit_and);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_bit_or_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_bit_or(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_bit_or);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_bit_xor_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_bit_xor(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_bit_xor);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_add_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_add(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_add);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_sub_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_sub(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_sub);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_mul_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_mul(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_mul);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_div_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_div(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_div);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_mod_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_mod(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_mod);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_shl_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_shl(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_shl);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_shr_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_shr(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_shr);
|
||||
}
|
||||
|
||||
void __qmljs_inplace_ushr_member(Value value, Value base, String *name, Context *ctx)
|
||||
{
|
||||
Object *o = base.objectValue();
|
||||
Value prop = o->__get__(ctx, name);
|
||||
prop = __qmljs_ushr(prop, value, ctx);
|
||||
o->__put__(ctx, name, prop);
|
||||
Object *o = base.toObject(ctx).objectValue();
|
||||
o->inplaceBinOp(value, ctx, name, __qmljs_ushr);
|
||||
}
|
||||
|
||||
String *__qmljs_string_from_utf8(Context *ctx, const char *s)
|
||||
|
|
|
|||
|
|
@ -351,6 +351,8 @@ void __qmljs_delete_exception_handler(Context *context);
|
|||
Value __qmljs_get_exception(Context *context);
|
||||
|
||||
// binary operators
|
||||
typedef Value (*BinOp)(Value left, Value right, Context *ctx);
|
||||
|
||||
Value __qmljs_instanceof(Value left, Value right, Context *ctx);
|
||||
Value __qmljs_in(Value left, Value right, Context *ctx);
|
||||
Value __qmljs_bit_or(Value left, Value right, Context *ctx);
|
||||
|
|
|
|||
Loading…
Reference in New Issue