mirror of https://github.com/adamdruppe/arsd.git
fix more property wrapping stuff
This commit is contained in:
parent
db857a4470
commit
1debdf7cc7
60
jsvar.d
60
jsvar.d
|
@ -808,7 +808,14 @@ struct var {
|
||||||
|
|
||||||
public var opOpAssign(string op, T)(T t) {
|
public var opOpAssign(string op, T)(T t) {
|
||||||
if(payloadType() == Type.Object) {
|
if(payloadType() == Type.Object) {
|
||||||
if(this._payload._object !is null) {
|
if(auto pt = cast(PropertyPrototype) this._payload._object) {
|
||||||
|
auto propValue = pt.get;
|
||||||
|
auto result = propValue.opOpAssign!(op)(t);
|
||||||
|
|
||||||
|
pt.set(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} else if(this._payload._object !is null) {
|
||||||
var* operator = this._payload._object._peekMember("opOpAssign", true);
|
var* operator = this._payload._object._peekMember("opOpAssign", true);
|
||||||
if(operator !is null && operator._type == Type.Function)
|
if(operator !is null && operator._type == Type.Function)
|
||||||
return operator.call(this, op, t);
|
return operator.call(this, op, t);
|
||||||
|
@ -1375,7 +1382,7 @@ struct var {
|
||||||
else
|
else
|
||||||
return *(new var);
|
return *(new var);
|
||||||
}
|
}
|
||||||
return from._getMember(name, true, false, file, line);
|
return from._getMember(name, true, false, false, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref var opIndexAssign(T)(T t, string name, string file = __FILE__, size_t line = __LINE__) {
|
public ref var opIndexAssign(T)(T t, string name, string file = __FILE__, size_t line = __LINE__) {
|
||||||
|
@ -1823,12 +1830,14 @@ class PrototypeObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: maybe throw something else
|
// FIXME: maybe throw something else
|
||||||
/*package*/ ref var _getMember(string name, bool recurse, bool throwOnFailure, string file = __FILE__, size_t line = __LINE__) {
|
/*package*/ ref var _getMember(string name, bool recurse, bool throwOnFailure, bool returnRawProperty = false, string file = __FILE__, size_t line = __LINE__) {
|
||||||
var* mem = _peekMember(name, recurse);
|
var* mem = _peekMember(name, recurse);
|
||||||
|
|
||||||
if(mem !is null) {
|
if(mem !is null) {
|
||||||
// If it is a property, we need to call the getter on it
|
// If it is a property, we need to call the getter on it
|
||||||
if((*mem).payloadType == var.Type.Object && cast(PropertyPrototype) (*mem)._payload._object) {
|
if((*mem).payloadType == var.Type.Object && cast(PropertyPrototype) (*mem)._payload._object) {
|
||||||
|
if(returnRawProperty)
|
||||||
|
return *mem;
|
||||||
auto prop = cast(PropertyPrototype) (*mem)._payload._object;
|
auto prop = cast(PropertyPrototype) (*mem)._payload._object;
|
||||||
return prop.get;
|
return prop.get;
|
||||||
}
|
}
|
||||||
|
@ -1854,14 +1863,25 @@ class PrototypeObject {
|
||||||
/*package*/ ref var _setMember(string name, var t, bool recurse, bool throwOnFailure, bool suppressOverloading, string file = __FILE__, size_t line = __LINE__) {
|
/*package*/ ref var _setMember(string name, var t, bool recurse, bool throwOnFailure, bool suppressOverloading, string file = __FILE__, size_t line = __LINE__) {
|
||||||
var* mem = _peekMember(name, recurse);
|
var* mem = _peekMember(name, recurse);
|
||||||
|
|
||||||
|
bool onParent = false;
|
||||||
|
|
||||||
|
if(mem is null && !recurse) {
|
||||||
|
mem = _peekMember(name, true); // properties need the check anyway as a setter might be on a prototype
|
||||||
|
onParent = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(mem !is null) {
|
if(mem !is null) {
|
||||||
// Property check - the setter should be proxied over to it
|
// Property check - the setter should be proxied over to it
|
||||||
if((*mem).payloadType == var.Type.Object && cast(PropertyPrototype) (*mem)._payload._object) {
|
if((*mem).payloadType == var.Type.Object && cast(PropertyPrototype) (*mem)._payload._object) {
|
||||||
auto prop = cast(PropertyPrototype) (*mem)._payload._object;
|
auto prop = cast(PropertyPrototype) (*mem)._payload._object;
|
||||||
return prop.set(t);
|
return prop.set(t);
|
||||||
}
|
}
|
||||||
*mem = t;
|
if(!onParent) {
|
||||||
return *mem;
|
*mem = t;
|
||||||
|
return *mem;
|
||||||
|
} else {
|
||||||
|
mem = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!suppressOverloading) {
|
if(!suppressOverloading) {
|
||||||
|
@ -2369,6 +2389,36 @@ unittest {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(with_arsd_script)
|
||||||
|
unittest {
|
||||||
|
import arsd.script;
|
||||||
|
static class Test {
|
||||||
|
@scriptable int a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Test test = new Test;
|
||||||
|
|
||||||
|
test.a = 15;
|
||||||
|
|
||||||
|
var globals = var.emptyObject;
|
||||||
|
globals.test = test;
|
||||||
|
globals.Test = subclassable!Test;
|
||||||
|
|
||||||
|
interpret(q{
|
||||||
|
test.a = 4;
|
||||||
|
var wtf = test.a += 5;
|
||||||
|
assert(wtf == 9);
|
||||||
|
assert(test.a == 9);
|
||||||
|
var test2 = new Test;
|
||||||
|
test2.a = 2;
|
||||||
|
test2.a += 5;
|
||||||
|
assert(test2.a == 7);
|
||||||
|
}, globals);
|
||||||
|
|
||||||
|
assert(test.a == 9);
|
||||||
|
assert(globals.test2.get!Test.a == 7);
|
||||||
|
}
|
||||||
|
|
||||||
// just a base class we can reference when looking for native objects
|
// just a base class we can reference when looking for native objects
|
||||||
class WrappedNativeObject : PrototypeObject {
|
class WrappedNativeObject : PrototypeObject {
|
||||||
TypeInfo wrappedType;
|
TypeInfo wrappedType;
|
||||||
|
|
29
script.d
29
script.d
|
@ -1503,7 +1503,7 @@ class OpAssignExpression : Expression {
|
||||||
var n;
|
var n;
|
||||||
foreach(ctOp; CtList!("+=", "-=", "*=", "/=", "~=", "&=", "|=", "^=", "%="))
|
foreach(ctOp; CtList!("+=", "-=", "*=", "/=", "~=", "&=", "|=", "^=", "%="))
|
||||||
if(ctOp[0..1] == op)
|
if(ctOp[0..1] == op)
|
||||||
n = mixin("v.getVar(sc) "~ctOp~" right");
|
n = mixin("v.getVar(sc, true, true) "~ctOp~" right");
|
||||||
|
|
||||||
// FIXME: ensure the variable is updated in scope too
|
// FIXME: ensure the variable is updated in scope too
|
||||||
|
|
||||||
|
@ -1579,9 +1579,9 @@ class VariableExpression : Expression {
|
||||||
return getVar(sc).get!string;
|
return getVar(sc).get!string;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref var getVar(PrototypeObject sc, bool recurse = true) {
|
ref var getVar(PrototypeObject sc, bool recurse = true, bool returnRawProperty = false) {
|
||||||
try {
|
try {
|
||||||
return sc._getMember(identifier, true /* FIXME: recurse?? */, true);
|
return sc._getMember(identifier, true /* FIXME: recurse?? */, true, returnRawProperty);
|
||||||
} catch(DynamicTypeException dte) {
|
} catch(DynamicTypeException dte) {
|
||||||
dte.callStack ~= loc;
|
dte.callStack ~= loc;
|
||||||
throw dte;
|
throw dte;
|
||||||
|
@ -1592,7 +1592,12 @@ class VariableExpression : Expression {
|
||||||
return sc._setMember(identifier, t, true /* FIXME: recurse?? */, true, suppressOverloading);
|
return sc._setMember(identifier, t, true /* FIXME: recurse?? */, true, suppressOverloading);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref var getVarFrom(PrototypeObject sc, ref var v) {
|
ref var getVarFrom(PrototypeObject sc, ref var v, bool returnRawProperty) {
|
||||||
|
if(returnRawProperty) {
|
||||||
|
if(v.payloadType == var.Type.Object)
|
||||||
|
return v._payload._object._getMember(identifier, true, false, returnRawProperty);
|
||||||
|
}
|
||||||
|
|
||||||
return v[identifier];
|
return v[identifier];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1658,7 +1663,7 @@ class DotVarExpression : VariableExpression {
|
||||||
return e1.toString() ~ "." ~ e2.toString();
|
return e1.toString() ~ "." ~ e2.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
override ref var getVar(PrototypeObject sc, bool recurse = true) {
|
override ref var getVar(PrototypeObject sc, bool recurse = true, bool returnRawProperty = false) {
|
||||||
if(!this.recurse) {
|
if(!this.recurse) {
|
||||||
// this is a special hack...
|
// this is a special hack...
|
||||||
if(auto ve = cast(VariableExpression) e1) {
|
if(auto ve = cast(VariableExpression) e1) {
|
||||||
|
@ -1676,7 +1681,7 @@ class DotVarExpression : VariableExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto ve = cast(VariableExpression) e1) {
|
if(auto ve = cast(VariableExpression) e1) {
|
||||||
return this.getVarFrom(sc, ve.getVar(sc, recurse));
|
return this.getVarFrom(sc, ve.getVar(sc, recurse), returnRawProperty);
|
||||||
} else if(cast(StringLiteralExpression) e1 && e2.identifier == "interpolate") {
|
} else if(cast(StringLiteralExpression) e1 && e2.identifier == "interpolate") {
|
||||||
auto se = cast(StringLiteralExpression) e1;
|
auto se = cast(StringLiteralExpression) e1;
|
||||||
var* functor = new var;
|
var* functor = new var;
|
||||||
|
@ -1690,7 +1695,7 @@ class DotVarExpression : VariableExpression {
|
||||||
// make a temporary for the lhs
|
// make a temporary for the lhs
|
||||||
auto v = new var();
|
auto v = new var();
|
||||||
*v = e1.interpret(sc).value;
|
*v = e1.interpret(sc).value;
|
||||||
return this.getVarFrom(sc, *v);
|
return this.getVarFrom(sc, *v, returnRawProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1702,8 +1707,8 @@ class DotVarExpression : VariableExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override ref var getVarFrom(PrototypeObject sc, ref var v) {
|
override ref var getVarFrom(PrototypeObject sc, ref var v, bool returnRawProperty) {
|
||||||
return e2.getVarFrom(sc, v);
|
return e2.getVarFrom(sc, v, returnRawProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toInterpretedString(PrototypeObject sc) {
|
override string toInterpretedString(PrototypeObject sc) {
|
||||||
|
@ -1725,13 +1730,13 @@ class IndexExpression : VariableExpression {
|
||||||
return e1.toString() ~ "[" ~ e2.toString() ~ "]";
|
return e1.toString() ~ "[" ~ e2.toString() ~ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
override ref var getVar(PrototypeObject sc, bool recurse = true) {
|
override ref var getVar(PrototypeObject sc, bool recurse = true, bool returnRawProperty = false) {
|
||||||
if(auto ve = cast(VariableExpression) e1)
|
if(auto ve = cast(VariableExpression) e1)
|
||||||
return ve.getVar(sc, recurse)[e2.interpret(sc).value];
|
return ve.getVar(sc, recurse, returnRawProperty)[e2.interpret(sc).value];
|
||||||
else {
|
else {
|
||||||
auto v = new var();
|
auto v = new var();
|
||||||
*v = e1.interpret(sc).value;
|
*v = e1.interpret(sc).value;
|
||||||
return this.getVarFrom(sc, *v);
|
return this.getVarFrom(sc, *v, returnRawProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue