I think i fixed classes

This commit is contained in:
Ne_Eo
2024-09-03 01:21:39 +02:00
parent 6db0f7c60b
commit a565cb7b2a
4 changed files with 204 additions and 106 deletions
+71 -27
View File
@@ -28,32 +28,41 @@ class CustomClassHandler implements IHScriptCustomConstructor {
}
public function hnew(args:Array<Dynamic>):Dynamic {
// TODO: clean this up, it sucks, i hate it
var interp = new Interp();
interp.errorHandler = ogInterp.errorHandler;
var _class:IHScriptCustomClassBehaviour = Type.createInstance(cl, args);
var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
var capturedLocals:Map<String, DeclaredVar> = [];
for(k=>e in __capturedLocals)
if (e != null && e.depth <= 0)
capturedLocals.set(k, e);
//var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
//var capturedLocals:Map<String, DeclaredVar> = [];
//for(k=>e in __capturedLocals)
// if (e != null && e.depth <= 0)
// capturedLocals.set(k, e);
var disallowCopy = Type.getInstanceFields(cl);
for (key => value in capturedLocals) {
if(!disallowCopy.contains(key)) {
interp.locals.set(key, {r: value, depth: -1});
}
}
_class.__real_fields = disallowCopy;
// todo: make it so you can use variables from the same scope as where the class was defined
//for (key => value in capturedLocals) {
// if(!disallowCopy.contains(key)) {
// interp.locals.set(key, {r: value, depth: -1});
// }
//}
for (key => value in ogInterp.variables) {
if(!disallowCopy.contains(key)) {
interp.variables.set(key, value);
}
}
var comparisonMap = new Map();
//trace("Before: " + [for(key => value in interp.variables) key]);
interp.variables.set("super", staticHandler);
var comparisonMap:Map<String, Dynamic> = [];
for(key => value in interp.variables) {
comparisonMap.set(key, value);
}
@@ -61,34 +70,39 @@ class CustomClassHandler implements IHScriptCustomConstructor {
_class.__custom__variables = interp.variables;
//trace(fields);
for(expr in fields) {
@:privateAccess
interp.exprReturn(expr);
}
interp.variables.set("super", staticHandler);
//trace("After: " + [for(key => value in interp.variables) key]);
_class.__interp = interp;
interp.scriptObject = _class;
// get only variables that were not set before
var classVariables = [for(key => value in interp.variables) if(!comparisonMap.exists(key) || comparisonMap[key] != value) key => value];
for(variable => value in classVariables) {
if(variable == "this" || variable == "super") continue;
@:privateAccess
if(!interp.__instanceFields.contains(variable)) {
interp.__instanceFields.push(variable);
}
}
var classVariables = [
for(key => value in interp.variables)
if(!comparisonMap.exists(key) || comparisonMap[key] != value)
key => value
];
//for(variable => value in classVariables) {
// if(variable == "this" || variable == "super" || variable == "new") continue;
// @:privateAccess
// if(!interp.__instanceFields.contains(variable)) {
// interp.__instanceFields.push(variable);
// }
//}
//trace([for(key => value in classVariables) key]);
_class.__class__fields = [for(key => value in classVariables) key];
//trace(_class.__class__fields);
//@:privateAccess
//trace(interp.__instanceFields);
_class.__interp = interp;
_class.__allowSetGet = false;
interp.scriptObject = _class;
for(variable => value in interp.variables) {
if(variable == "this") continue;
if(variable == "this" || variable == "super" || variable == "new") continue;
if(variable.startsWith("set_") || variable.startsWith("get_")) {
_class.__allowSetGet = true;
@@ -97,9 +111,32 @@ class CustomClassHandler implements IHScriptCustomConstructor {
var newFunc = interp.variables.get("new");
if(newFunc != null) {
var comparisonMap:Map<String, Dynamic> = [];
for(key => value in interp.variables) {
comparisonMap.set(key, value);
}
UnsafeReflect.callMethodUnsafe(null, newFunc, args);
// get only variables that were not set before
var classVariables = [
for(key => value in interp.variables)
if(!comparisonMap.exists(key) || comparisonMap[key] != value)
key => value
];
for(variable => value in classVariables) {
if(variable == "this" || variable == "super" || variable == "new") continue;
@:privateAccess
if(!interp.__instanceFields.contains(variable)) {
interp.__instanceFields.push(variable);
}
if(!_class.__class__fields.contains(variable)) {
_class.__class__fields.push(variable);
}
}
}
return _class;
}
@@ -112,6 +149,8 @@ class TemplateClass implements IHScriptCustomClassBehaviour implements IHScriptC
public var __interp:Interp;
public var __allowSetGet:Bool = true;
public var __custom__variables:Map<String, Dynamic>;
public var __real_fields:Array<String>;
public var __class__fields:Array<String>;
public function hset(name:String, val:Dynamic):Dynamic {
if(__allowSetGet && __custom__variables.exists("set_" + name))
@@ -120,14 +159,19 @@ class TemplateClass implements IHScriptCustomClassBehaviour implements IHScriptC
__custom__variables.set(name, val);
return val;
}
UnsafeReflect.setProperty(this, name, val);
return UnsafeReflect.field(this, name);
if(__real_fields.contains(name)) {
UnsafeReflect.setProperty(this, name, val);
return UnsafeReflect.field(this, name);
}
__custom__variables.set(name, val);
return val;
}
public function hget(name:String):Dynamic {
if(__allowSetGet && __custom__variables.exists("get_" + name))
return __callGetter(name);
if (__custom__variables.exists(name))
return __custom__variables.get(name);
return UnsafeReflect.getProperty(this, name);
}
+2
View File
@@ -4,6 +4,8 @@ interface IHScriptCustomClassBehaviour {
public var __interp:Interp;
public var __custom__variables:Map<String, Dynamic>;
public var __allowSetGet:Bool;
public var __real_fields:Array<String>;
public var __class__fields:Array<String>;
public function hset(name:String, val:Dynamic):Dynamic;
public function hget(name:String):Dynamic;
+94 -54
View File
@@ -28,6 +28,7 @@
*/
package hscript;
import haxe.CallStack;
import hscript.utils.UnsafeReflect;
import haxe.PosInfos;
import hscript.Expr;
@@ -45,8 +46,8 @@ enum abstract ScriptObjectType(UInt8) {
var SClass;
var SObject;
var SStaticClass;
var SCustomClass;
var SBehaviourClass;
var SCustomClass; // custom classes
var SBehaviourClass; // hget and hset
var SNull;
}
@@ -71,9 +72,12 @@ class Interp {
switch(Type.typeof(v)) {
case TClass(c): // Class Access
__instanceFields = Type.getInstanceFields(c);
if(c is IHScriptCustomClassBehaviour) {
if(v is IHScriptCustomClassBehaviour) {
var v = cast(v, IHScriptCustomClassBehaviour);
if(v.__class__fields != null)
__instanceFields = __instanceFields.concat(v.__class__fields);
_scriptObjectType = SCustomClass;
} else if(c is IHScriptCustomBehaviour) {
} else if(v is IHScriptCustomBehaviour) {
_scriptObjectType = SBehaviourClass;
} else {
_scriptObjectType = SClass;
@@ -266,35 +270,36 @@ class Interp {
case EIdent(id):
if (!locals.exists(id)) {
if (_hasScriptObject && !varExists(id)) {
if (_scriptObjectType == SObject) {
var instanceHasField = __instanceFields.contains(id);
if (_scriptObjectType == SObject && instanceHasField) {
UnsafeReflect.setField(scriptObject, id, v);
} else {
if (_scriptObjectType == SCustomClass) {
var obj = cast(scriptObject, IHScriptCustomClassBehaviour);
if(isBypassAccessor) {
obj.__allowSetGet = false;
var res = obj.hset(id, v);
obj.__allowSetGet = true;
return res;
}
return obj.hset(id, v);
} else if (_scriptObjectType == SBehaviourClass) {
var obj = cast(scriptObject, IHScriptCustomBehaviour);
return obj.hset(id, v);
} else if (_scriptObjectType == SCustomClass && instanceHasField) {
var obj = cast(scriptObject, IHScriptCustomClassBehaviour);
if(isBypassAccessor) {
obj.__allowSetGet = false;
var res = obj.hset(id, v);
obj.__allowSetGet = true;
return res;
}
if (isBypassAccessor) {
if (__instanceFields.contains(id)) {
UnsafeReflect.setField(scriptObject, id, v);
return v;
}
}
if (__instanceFields.contains(id)) {
UnsafeReflect.setProperty(scriptObject, id, v);
} else if (__instanceFields.contains('set_$id')) { // setter
UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
return obj.hset(id, v);
} else if (_scriptObjectType == SBehaviourClass) {
var obj = cast(scriptObject, IHScriptCustomBehaviour);
return obj.hset(id, v);
}
if (instanceHasField) {
if(isBypassAccessor) {
UnsafeReflect.setField(scriptObject, id, v);
return v;
} else {
setVar(id, v);
UnsafeReflect.setProperty(scriptObject, id, v);
return UnsafeReflect.field(scriptObject, id);
}
} else if (__instanceFields.contains('set_$id')) { // setter
return UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
} else {
setVar(id, v);
}
} else {
setVar(id, v);
@@ -339,10 +344,12 @@ class Interp {
v = fop(expr(e1), expr(e2));
if (l == null) {
if(_hasScriptObject) {
if(_scriptObjectType == SObject) {
var instanceHasField = __instanceFields.contains(id);
if(_scriptObjectType == SObject && instanceHasField) {
UnsafeReflect.setField(scriptObject, id, v);
return v;
} else if (_scriptObjectType == SCustomClass) {
} else if (_scriptObjectType == SCustomClass && instanceHasField) {
var obj = cast(scriptObject, IHScriptCustomClassBehaviour);
if(isBypassAccessor) {
obj.__allowSetGet = false;
@@ -356,17 +363,16 @@ class Interp {
return obj.hset(id, v);
}
if (isBypassAccessor) {
if (__instanceFields.contains(id)) {
if (instanceHasField) {
if(isBypassAccessor) {
UnsafeReflect.setField(scriptObject, id, v);
return v;
} else {
UnsafeReflect.setProperty(scriptObject, id, v);
return UnsafeReflect.field(scriptObject, id);
}
}
if (__instanceFields.contains(id)) {
UnsafeReflect.setProperty(scriptObject, id, v);
} else if (__instanceFields.contains('set_$id')) { // setter
UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
return UnsafeReflect.getProperty(scriptObject, 'set_$id')(v);
} else {
setVar(id, v);
}
@@ -559,9 +565,12 @@ class Interp {
// search in object
if (id == "this") {
return scriptObject;
} else if (_scriptObjectType == SObject && UnsafeReflect.hasField(scriptObject, id)) {
}
var instanceHasField = __instanceFields.contains(id);
if (_scriptObjectType == SObject && instanceHasField) {
return UnsafeReflect.field(scriptObject, id);
} else if(_scriptObjectType == SCustomClass) {
} else if(_scriptObjectType == SCustomClass && instanceHasField) {
var obj = cast(scriptObject, IHScriptCustomClassBehaviour);
if(isBypassAccessor) {
obj.__allowSetGet = false;
@@ -574,12 +583,11 @@ class Interp {
var obj = cast(scriptObject, IHScriptCustomBehaviour);
return obj.hget(id);
}
else {
if (__instanceFields.contains(id)) {
return UnsafeReflect.getProperty(scriptObject, id);
} else if (__instanceFields.contains('get_$id')) { // getter
return UnsafeReflect.getProperty(scriptObject, 'get_$id')();
}
if (instanceHasField) {
return UnsafeReflect.getProperty(scriptObject, id);
} else if (__instanceFields.contains('get_$id')) { // getter
return UnsafeReflect.getProperty(scriptObject, 'get_$id')();
}
}
if (doException)
@@ -687,13 +695,14 @@ class Interp {
declared.push({n: n, old: locals.get(n), depth: depth});
locals.set(n, {r: (e == null) ? null : expr(e), depth: depth});
if (depth == 0) {
if(isStatic == true) {
if(!staticVariables.exists(n)) {
if(allowStaticVariables && isStatic == true) {
if(!staticVariables.exists(n)) // make it so it only sets it once
staticVariables.set(n, locals[n].r);
}
return null;
} else if(allowPublicVariables && isPublic == true) {
publicVariables.set(n, locals[n].r);
} else {
variables.set(n, locals[n].r);
}
(isPublic ? publicVariables : variables).set(n, locals[n].r);
}
return null;
case EParent(e):
@@ -835,7 +844,13 @@ class Interp {
if (name != null) {
if (depth == 0) {
// global function
((isStatic && allowStaticVariables) ? staticVariables : ((isPublic && allowPublicVariables) ? publicVariables : variables)).set(name, f);
if(isStatic && allowStaticVariables) {
staticVariables.set(name, f);
} else if(isPublic && allowPublicVariables) {
publicVariables.set(name, f);
} else {
variables.set(name, f);
}
} else {
// function-in-function is a local function
declared.push({n: name, old: locals.get(name), depth: depth});
@@ -1126,7 +1141,20 @@ class Interp {
cl != null && getRedirects.exists(cl) && (_getRedirect = getRedirects[cl]) != null;
}) {
return _getRedirect(o, f);
} else if (o is IHScriptCustomBehaviour) {
}
if(o is IHScriptCustomClassBehaviour) {
var obj = cast(o, IHScriptCustomClassBehaviour);
if(isBypassAccessor) {
obj.__allowSetGet = false;
var res = obj.hget(f);
obj.__allowSetGet = true;
return res;
}
return obj.hget(f);
}
if (o is IHScriptCustomBehaviour) {
var obj = cast(o, IHScriptCustomBehaviour);
return obj.hget(f);
}
@@ -1152,7 +1180,19 @@ class Interp {
cl != null && setRedirects.exists(cl) && (_setRedirect = setRedirects[cl]) != null;
})
return _setRedirect(o, f, v);
else if (o is IHScriptCustomBehaviour) {
if(o is IHScriptCustomClassBehaviour) {
var obj = cast(o, IHScriptCustomClassBehaviour);
if(isBypassAccessor) {
obj.__allowSetGet = false;
var res = obj.hset(f, v);
obj.__allowSetGet = true;
return res;
}
return obj.hset(f, v);
}
if (o is IHScriptCustomBehaviour) {
var obj = cast(o, IHScriptCustomBehaviour);
return obj.hset(f, v);
}
+37 -25
View File
@@ -285,31 +285,35 @@ class ClassExtendMacro {
shadowClass.fields.push({
name: "__interp",
pos: Context.currentPos(),
kind: FVar(TPath({
pack: ['hscript'],
name: 'Interp'
})),
kind: FVar(macro: hscript.Interp),
access: [APublic]
});
shadowClass.fields.push({
name: "__custom__variables",
pos: Context.currentPos(),
kind: FVar(TPath({
pack: [],
name: 'Map',
params: [TPType(TPath({name: "String", pack: []})), TPType(TPath({name: "Dynamic", pack: []}))]
})),
kind: FVar(macro: Map<String, Dynamic>),
access: [APublic]
});
shadowClass.fields.push({
name: "__allowSetGet",
pos: Context.currentPos(),
kind: FVar(TPath({
pack: [],
name: 'Bool',
}), macro true),
kind: FVar(macro: Bool, macro true),
access: [APublic]
});
shadowClass.fields.push({
name: "__real_fields",
pos: Context.currentPos(),
kind: FVar(macro: Array<String>),
access: [APublic]
});
shadowClass.fields.push({
name: "__class__fields",
pos: Context.currentPos(),
kind: FVar(macro: Array<String>),
access: [APublic]
});
@@ -317,7 +321,7 @@ class ClassExtendMacro {
name: "__callGetter",
pos: Context.currentPos(),
kind: FFun({
ret: TPath({name: 'Dynamic', pack: []}),
ret: macro: Dynamic,
params: [],
expr: macro {
__allowSetGet = false;
@@ -330,7 +334,7 @@ class ClassExtendMacro {
name: "name",
opt: false,
meta: [],
type: TPath({name: "String", pack: []})
type: macro: String
}
]
}),
@@ -341,7 +345,7 @@ class ClassExtendMacro {
name: "__callSetter",
pos: Context.currentPos(),
kind: FFun({
ret: TPath({name: 'Dynamic', pack: []}),
ret: macro: Dynamic,
params: [],
expr: macro {
__allowSetGet = false;
@@ -354,13 +358,13 @@ class ClassExtendMacro {
name: "name",
opt: false,
meta: [],
type: TPath({name: "String", pack: []})
type: macro: String
},
{
name: "val",
opt: false,
meta: [],
type: TPath({name: "Dynamic", pack: []})
type: macro: Dynamic
}
]
}),
@@ -433,6 +437,10 @@ class ClassExtendMacro {
__custom__variables.set(name, val);
return val;
}
if(__real_fields.contains(name)) {
UnsafeReflect.setProperty(this, name, val);
return UnsafeReflect.field(this, name);
}
return super.hset(name, val);
}
} else {
@@ -443,8 +451,12 @@ class ClassExtendMacro {
__custom__variables.set(name, val);
return val;
}
UnsafeReflect.setProperty(this, name, val);
return UnsafeReflect.field(this, name);
if(__real_fields.contains(name)) {
UnsafeReflect.setProperty(this, name, val);
return UnsafeReflect.field(this, name);
}
__custom__variables.set(name, val);
return val;
}
}
@@ -457,7 +469,7 @@ class ClassExtendMacro {
pos: Context.currentPos(),
access: hasHsetInSuper ? [AOverride, APublic] : [APublic],
kind: FFun({
ret: TPath({name: 'Dynamic', pack: []}),
ret: macro: Dynamic,
params: [],
expr: hsetField,
args: [
@@ -465,13 +477,13 @@ class ClassExtendMacro {
name: "name",
opt: false,
meta: [],
type: TPath({name: "String", pack: []})
type: macro: String
},
{
name: "val",
opt: false,
meta: [],
type: TPath({name: "Dynamic", pack: []})
type: macro: Dynamic
}
]
})
@@ -482,7 +494,7 @@ class ClassExtendMacro {
pos: Context.currentPos(),
access: hasHgetInSuper ? [AOverride, APublic] : [APublic],
kind: FFun({
ret: TPath({name: 'Dynamic', pack: []}),
ret: macro: Dynamic,
params: [],
expr: hgetField,
args: [
@@ -490,7 +502,7 @@ class ClassExtendMacro {
name: "name",
opt: false,
meta: [],
type: TPath({name: "String", pack: []})
type: macro: String
}
]
})