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:
Lars Knoll 2012-11-10 23:35:06 +01:00
parent d5fe0946bd
commit 0c1424362f
4 changed files with 85 additions and 88 deletions

View File

@ -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();
}

View File

@ -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 {

View File

@ -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)

View File

@ -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);