Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 53 additions & 34 deletions polymod/hscript/_internal/Interp.hx
Original file line number Diff line number Diff line change
Expand Up @@ -1526,10 +1526,16 @@ class Interp
{
error(EInvalidInStaticContext("super"));
}
else if (_proxy.superClass == null)
else if (!_proxy._superConstructorCalled)
{
if (_proxy._c.extend == null) error(EClassInvalidSuper);
return Reflect.makeVarArgs(_proxy.createSuperClass);
if (_proxy._c.extend == null)
error(EClassInvalidSuper);

_proxy._superConstructorCalled = true;
if (Std.isOfType(_proxy.superClass, PolymodScriptClass))
return Reflect.makeVarArgs(_proxy.superClass.callConstructor); // We will be calling the superclass constructor.
else
return Reflect.makeVarArgs(_proxy.createSuperClass); // We can't get a native class constructor at runtime right now unfortunately, so we just return the class itself to instantiate it.
}
else
{
Expand Down Expand Up @@ -1624,45 +1630,58 @@ class Interp
if (result != null) return result;
}

// We are calling a LOCAL function from the same module.
// We first check if any of the child classes has overridden the scripted function
if (_proxy != null && _proxy.topASC?.hasScriptFunction(id) ?? false)
if (_proxy != null)
{
_nextCallObject = _proxy.topASC;
return _proxy.topASC.resolveField(id);
}
if (_proxy != null && _proxy.findFunction(id, true) != null)
{
_nextCallObject = _proxy;
return _proxy.resolveField(id);
}
else if (_proxy != null && _proxy.superHasField(id))
{
_nextCallObject = _proxy.superClass;

if (Std.isOfType(_proxy.superClass, PolymodScriptClass))
// We are calling a LOCAL function from the same module.
// We first check if any of the child classes has overridden the scripted function
var topScriptClass = _proxy.getMostTopASC();
if (topScriptClass != _proxy)
{
var superClass:PolymodAbstractScriptClass = cast(_proxy.superClass, PolymodScriptClass);
return superClass.fieldRead(id);
while (Std.isOfType(topScriptClass, PolymodScriptClass))
{
if (topScriptClass.hasScriptFunction(id) ?? false)
{
_nextCallObject = topScriptClass;
return topScriptClass.resolveField(id);
}
topScriptClass = topScriptClass.superClass;
}
}

return Reflect.getProperty(_proxy.superClass, id);
}
else if (_proxy != null && _proxy.hasPurgedScriptFunction(id))
{
error(EPurgedFunction(id));
}
else if (_proxy != null)
{
try
// Try to find the function within the scripted class itself.
if (_proxy.findFunction(id, true) != null)
{
var r = _proxy.resolveField(id);
_nextCallObject = _proxy;
return r;
return _proxy.resolveField(id);
}
catch (e:Dynamic)
else if (_proxy.superHasField(id))
{
_nextCallObject = _proxy.superClass;

if (Std.isOfType(_proxy.superClass, PolymodScriptClass))
{
var superClass:PolymodAbstractScriptClass = cast(_proxy.superClass, PolymodScriptClass);
return superClass.fieldRead(id);
}

return Reflect.getProperty(_proxy.superClass, id);
}
else if (_proxy.hasPurgedScriptFunction(id))
{
error(EPurgedFunction(id));
}
else
{
// Skip and fall through to the next case.
try
{
var r = _proxy.resolveField(id);
_nextCallObject = _proxy;
return r;
}
catch (e:Dynamic)
{
// Skip and fall through to the next case.
}
}
}

Expand Down
38 changes: 21 additions & 17 deletions polymod/hscript/_internal/PolymodAbstractScriptClass.hx
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,18 @@ abstract PolymodAbstractScriptClass(PolymodScriptClass) from PolymodScriptClass
this._interp._propTrack.set(getName, true);
var r:Dynamic = null;
// Children may override it
if (this.topASC != null && this.topASC.findFunction(getName) != null)
// Go from top to bottom when field searching.
var topASC = this.getMostTopASC();
while (topASC != null)
{
r = this.topASC.callFunction(getName);
if (topASC.findFunction(getName) != null)
{
r = topASC.callFunction(getName);
this._interp._propTrack.remove(getName);
return r;
}
topASC = topASC.superClass;
}
else
{
r = this.callFunction(getName);
}
this._interp._propTrack.remove(getName);
return r;
}
else
{
Expand Down Expand Up @@ -187,16 +189,18 @@ abstract PolymodAbstractScriptClass(PolymodScriptClass) from PolymodScriptClass
this._interp._propTrack.set(setName, true);
var r:Dynamic = null;
// Children may override it
if (this.topASC != null && this.topASC.findFunction(setName) != null)
{
r = this.topASC.callFunction(setName, [value]);
}
else
// Go from top to bottom when field searching.
var topASC = this.getMostTopASC();
while (topASC != null)
{
r = this.callFunction(setName, [value]);
if (topASC.findFunction(setName) != null)
{
r = topASC.callFunction(setName);
this._interp._propTrack.remove(setName);
return r;
}
topASC = topASC.superClass;
}
this._interp._propTrack.remove(setName);
return r;
}

case "never" | "null":
Expand All @@ -209,7 +213,7 @@ abstract PolymodAbstractScriptClass(PolymodScriptClass) from PolymodScriptClass
else if (this.findFunction(name) != null)
{
var fnDecl = this.findFunction(name, true);

if (fnDecl.isdynamic)
{
if (!Reflect.isFunction(value))
Expand Down
2 changes: 1 addition & 1 deletion polymod/hscript/_internal/PolymodCppiaClassReference.hx
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ class PolymodCppiaClassReference extends PolymodStaticClassReference
this.cppiaClass = cppiaClass;
}

override public function instantiate(?args:Array<Dynamic>):Null<Dynamic>
override public function instantiate(?args:Array<Dynamic>, constructor:Bool = true):Null<Dynamic>
{
if (cppiaClass == null)
{
Expand Down
95 changes: 76 additions & 19 deletions polymod/hscript/_internal/PolymodScriptClass.hx
Original file line number Diff line number Diff line change
Expand Up @@ -917,24 +917,47 @@ class PolymodScriptClass
buildCaches();
_interp.validateClassMetadata();

// Instantiate the super class first.
// Calling the constructor will be handled later.
if (_c.extend != null)
{
createSuperClass();
}
}

public function callConstructor(?args:Array<Dynamic>):Void
{
var ctorField = findField("new");
if (ctorField != null)
{
// The superclass constructor will be called inside of here.
callFunction("new", args);
if (superClass == null && _c.extend != null)
if (_c.extend != null && !_superConstructorCalled)
{
_interp.error(EClassSuperNotCalled);
}
}
else if (_c.extend != null)
{
createSuperClass(args);
_superConstructorCalled = true;

// This class doesn't have a custom constructor, so we use the superclasses constructor.
if (Std.isOfType(superClass, PolymodScriptClass))
{
superClass.callConstructor(args);
}
else
{
// Create the native super class since we don't have a custom constructor
createSuperClass(args);
}
}
_constructorArgs = args;

validateClassFields();
}

var _superConstructorCalled:Bool = false;
var __superClassFieldList:Array<String> = null;

public function superHasField(name:String):Bool
Expand Down Expand Up @@ -972,15 +995,7 @@ class PolymodScriptClass

private function createSuperClass(args:Array<Dynamic> = null)
{
if (_c.extend == null)
{
_interp.error(EClassInvalidSuper);
}

if (args == null)
{
args = [];
}
args ??= [];

var fullExtendString = new Printer().typeToString(_c.extend);

Expand All @@ -991,17 +1006,36 @@ class PolymodScriptClass
}

// Build an unqualified path too.
var fullExtendPath:String = _c.imports.get(fullExtendString)?.fullPath ?? fullExtendString;
var fullExtendStringParts = fullExtendString.split('.');
var extendString = fullExtendStringParts[fullExtendStringParts.length - 1];

var classDescriptor = Interp.findScriptClassDescriptor(fullExtendString);
var classDescriptor = Interp.findScriptClassDescriptor(fullExtendPath);
if (classDescriptor != null)
{
var abstractSuperClass:PolymodAbstractScriptClass = new PolymodScriptClass(classDescriptor, args);
superClass = abstractSuperClass;
var ref:PolymodStaticClassReference = PolymodStaticClassReference.tryBuild(fullExtendPath);

var clsInstance = ref.instantiate(args, false);
if (clsInstance != null)
{
if (Std.isOfType(clsInstance, PolymodScriptClass))
superClass = clsInstance;

// Set the top ASC to this class.
// This'll be recursive to other classes for if the superclass extends something else.
superClass.topASC = this;
}
else
{
superClass = null;
}
}
else
{
// We'll wait for the super constructor for it to be called.
if (!_superConstructorCalled)
return;

var clsToCreate:Class<Dynamic> = null;

#if POLYMOD_CPPIA
Expand All @@ -1027,10 +1061,13 @@ class PolymodScriptClass
}
else
{
_interp.error(EClassUnresolvedSuperclass(extendString, 'missing import'));
clsToCreate = _interp.resolveDottedPath(fullExtendPath);
}

superClass = Type.createInstance(clsToCreate, args);

// Set the asc field to be the most topASC class.
// This is because native class functions call asc script functions from top to bottom.
Reflect.setField(superClass, '_asc', getMostTopASC());
}
}

Expand All @@ -1051,7 +1088,7 @@ class PolymodScriptClass
if (f.access.contains(AOverride) && !superHasField(f.name))
{
// Throw an error if a function is declared overwritten but isn't overriding anything.
throw 'Field ' + '"${f.name}"' + 'is declared "override"' + "but doesn't override any field.";
throw 'Field ' + '"${f.name}"' + ' is declared "override"' + " but doesn't override any field.";
}
else if (!f.access.contains(AOverride) && superHasField(f.name))
{
Expand Down Expand Up @@ -1226,7 +1263,7 @@ class PolymodScriptClass

return false;
}

/**
* Checks if the class has a script function with the given name,
* which has been purged due to an uncaught exception when it was previously called.
Expand Down Expand Up @@ -1320,6 +1357,26 @@ class PolymodScriptClass
}
}

/**
* Retrieves the most top abstract script class of this instance.
* @return Null<PolymodAbstractScriptClass
*/
public function getMostTopASC():Null<PolymodAbstractScriptClass>
{
if (topASC == null)
return this;

var mostTopASC = this.topASC;
while (mostTopASC != null)
{
if (mostTopASC.topASC == null)
return mostTopASC;

mostTopASC = mostTopASC.topASC;
}
return null;
}

/**
* Search for a function field with the given name. Excludes variables and static functions.
* @param name The name of the function to search for.
Expand Down Expand Up @@ -1453,7 +1510,7 @@ class PolymodScriptClass
return _cachedFunctionDecls;
}

private final _constructorArgs:Array<Dynamic>;
private var _constructorArgs(default, null):Array<Dynamic>;

private var _cachedFieldDecls:Map<String, FieldDecl> = [];
private var _cachedSuperFunctionDecls:Map<String, Dynamic> = [];
Expand Down
Loading
Loading