Skip to content
Open
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
11 changes: 9 additions & 2 deletions polymod/hscript/_internal/Interp.hx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ class Interp

function assign(e1:Expr, e2:Expr):Dynamic
{
var v = expr(e2);
return assignValue(e1, expr(e2));
}

function assignValue(e1:Expr, v:Dynamic, _abstractInlineAssign:Bool = false):Dynamic
{
switch (Tools.expr(e1))
{
case EIdent(id):
Expand All @@ -152,7 +156,10 @@ class Interp
}

default:
error(EInvalidOp("="));
if (!_abstractInlineAssign)
{
error(EInvalidOp("="));
}
}
return v;
}
Expand Down
49 changes: 33 additions & 16 deletions polymod/hscript/_internal/PolymodClassDeclEx.hx
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,16 @@ class PolymodStaticAbstractReference
public var absImpl:Null<Class<Dynamic>>;

/**
* The path of the implementation class.
* Used for resolving static fields cached at macro time.
* The class, generated by Polymod, that implements the abstract class's static fields as well as inline instance functions,
* if it exists.
*/
public var absImplPath:String;
public var polymodImpl:Null<Class<Dynamic>>;

public function new(absName:String, absImpl:Null<Class<Dynamic>>, absImplPath:String)
public function new(absName:String, absImpl:Null<Class<Dynamic>>, polymodImpl:Null<Class<Dynamic>>)
{
this.absName = absName;
this.absImpl = absImpl;
this.absImplPath = absImplPath;
this.polymodImpl = polymodImpl;
}

/**
Expand Down Expand Up @@ -211,7 +211,17 @@ class PolymodStaticAbstractReference
}
}

return fetchAbstractClassStatic(fieldName);
if (this.polymodImpl != null)
{
var getterName:String = 'get_$fieldName';
if (Reflect.hasField(this.polymodImpl, getterName))
{
var getter = Reflect.field(this.polymodImpl, getterName);
return Reflect.callMethod(this.polymodImpl, getter, []);
}
}

throw 'Could not resolve abstract class static field ${fieldName}';
}

/**
Expand Down Expand Up @@ -259,21 +269,28 @@ class PolymodStaticAbstractReference
throw 'Could not resolve abstract class static function ${funcName}';
}

function fetchAbstractClassStatic(fieldName:String):Dynamic
public function hasInlineFunction(funcName:String):Bool
{
var key:String = '${this.absImplPath}.${fieldName}';

if (PolymodScriptClass.abstractClassStatics.exists(key))
if (this.polymodImpl != null)
{
var holder = PolymodScriptClass.abstractClassStatics.get(key);
var property = key.replace('.', '_');

return Reflect.getProperty(holder, property);
return Reflect.hasField(this.polymodImpl, funcName);
}
else

return false;
}

public function callInlineFunction(interp:PolymodInterpEx, absInstanceExpr:Expr, funcName:String, args:Array<Dynamic>):Dynamic
{
if (this.polymodImpl != null)
{
throw 'Could not resolve abstract class static field ${fieldName}';
var func = Reflect.field(this.polymodImpl, funcName);
if (func != null)
{
return Reflect.callMethod(this.polymodImpl, func, ([interp, absInstanceExpr] : Array<Dynamic>).concat(args));
}
}

throw 'Could not resolve abstract class inline instance function ${funcName}';
}

public function toString():String
Expand Down
35 changes: 22 additions & 13 deletions polymod/hscript/_internal/PolymodInterpEx.hx
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ class PolymodInterpEx extends Interp
super.setVar(id, v);
}

override function assign(e1:Expr, e2:Expr):Dynamic
override function assignValue(e1:Expr, v:Dynamic, _abstractInlineAssign:Bool = false):Dynamic
{
switch (Tools.expr(e1))
{
Expand All @@ -419,8 +419,6 @@ class PolymodInterpEx extends Interp
// Also ensures property functions are accounted for.
if (_proxy != null && _proxy.superHasField(id))
{
var v = expr(e2);

if (Std.isOfType(_proxy.superClass, PolymodScriptClass))
{
var superClass:PolymodAbstractScriptClass = cast(_proxy.superClass, PolymodScriptClass);
Expand All @@ -442,7 +440,6 @@ class PolymodInterpEx extends Interp
final setName = 'set_$id';
if (!_propTrack.exists(setName))
{
var v = expr(e2);
_propTrack.set(setName, true);
var out = _proxy.callFunction(setName, [v]);
_propTrack.remove(setName);
Expand Down Expand Up @@ -471,8 +468,6 @@ class PolymodInterpEx extends Interp
{
if (_proxy != null && _proxy.superHasField(id))
{
var v = expr(e2);

if (Std.isOfType(_proxy.superClass, PolymodScriptClass))
{
var superClass:PolymodAbstractScriptClass = cast(_proxy.superClass, PolymodScriptClass);
Expand Down Expand Up @@ -510,7 +505,7 @@ class PolymodInterpEx extends Interp
default:
}
// Fallback, which calls set()
return super.assign(e1, e2);
return super.assignValue(e1, v, _abstractInlineAssign);
}

override function increment(e:Expr, prefix:Bool, delta:Int)
Expand Down Expand Up @@ -875,14 +870,28 @@ class PolymodInterpEx extends Interp
{
case EField(e, f):
var name = getIdent(e);
name = getClassDecl().imports.get(name)?.fullPath ?? name;
if (name != null && _scriptEnumDescriptors.exists(name))
if (name != null)
{
var args = new Array();
for (p in params)
args.push(expr(p));
var imp = getClassDecl().imports.get(name);
if (imp != null)
{
if (_scriptEnumDescriptors.exists(imp.fullPath))
{
var args = new Array();
for (p in params)
args.push(expr(p));

return new PolymodEnum(_scriptEnumDescriptors.get(name), f, args);
return new PolymodEnum(_scriptEnumDescriptors.get(imp.fullPath), f, args);
}
else if (imp?.abs != null && imp.abs.hasInlineFunction(f))
{
var args = new Array();
for (p in params)
args.push(expr(p));

return imp.abs.callInlineFunction(this, params[0], f, args);
}
}
}
default:
}
Expand Down
29 changes: 2 additions & 27 deletions polymod/hscript/_internal/PolymodScriptClass.hx
Original file line number Diff line number Diff line change
Expand Up @@ -105,45 +105,20 @@ class PolymodScriptClass
var baseAbstractClassImpls:Map<String,
{
cls:Class<Dynamic>,
clsName:String,
polymodCls:Null<Class<Dynamic>>,
}> = PolymodScriptClassMacro.listAbstractImpls();

for (key => value in baseAbstractClassImpls)
{
if (value == null) continue;

_abstractClassImpls.set(key, new PolymodStaticAbstractReference(key, value.cls, value.clsName));
_abstractClassImpls.set(key, new PolymodStaticAbstractReference(key, value.cls, value.polymodCls));
}
}

return _abstractClassImpls;
}

/**
* Define a list of `fieldName -> Class` pointing to the generated class containing a reference
* to each static field of each abstract.
*/
public static var abstractClassStatics(get, never):Map<String, Class<Dynamic>>;

static var _abstractClassStatics:Map<String, Class<Dynamic>> = null;

static function get_abstractClassStatics():Map<String, Class<Dynamic>>
{
if (_abstractClassStatics == null)
{
_abstractClassStatics = new Map<String, Class<Dynamic>>();

var baseAbstractClassStatics:Map<String, Class<Dynamic>> = PolymodScriptClassMacro.listAbstractStatics();

for (key => value in baseAbstractClassStatics)
{
_abstractClassStatics.set(key, value);
}
}

return _abstractClassStatics;
}

/**
* Define a list of `typeName -> Class` which provides a reference to each typedef,
* since typedefs can't be normally resolved at runtime.
Expand Down
Loading