Enums, new import blocklist and redirects
warning: untested
This commit is contained in:
+22
-8
@@ -28,6 +28,9 @@
|
||||
*/
|
||||
package hscript;
|
||||
|
||||
import hscript.proxy.ProxyType;
|
||||
import hscript.Tools.EnumValue;
|
||||
import hscript.Tools.HScriptEnum;
|
||||
import haxe.Constraints.Function;
|
||||
import hscript.utils.UsingHandler;
|
||||
import hscript.customclass.CustomClassDecl;
|
||||
@@ -76,22 +79,26 @@ class RedeclaredVar {
|
||||
@:analyzer(optimize, local_dce, fusion, user_var_fusion)
|
||||
class Interp {
|
||||
private static var _customClasses:Map<String, CustomClassDecl> = new Map<String, CustomClassDecl>();
|
||||
private static var _customClassAliases:Map<String, String> = new Map<String, String>();
|
||||
|
||||
public static function getCustomClass(name:String) {
|
||||
// Retrieves the real class name
|
||||
var realName = _customClassAliases.get(name);
|
||||
if(realName != null) name = realName;
|
||||
return _customClasses.get(name);
|
||||
}
|
||||
|
||||
public static function customClassExist(name:String):Bool {
|
||||
return _customClasses.exists(name);
|
||||
return _customClassAliases.exists(name) || _customClasses.exists(name);
|
||||
}
|
||||
|
||||
private static function registerCustomClass(c:CustomClassDecl, ?as:String, ?inCustomClass:Bool) {
|
||||
#if CUSTOM_CLASSES
|
||||
var name = c.classDecl.name;
|
||||
if (as != null) name = as;
|
||||
else if (c.pkg != null && (inCustomClass != null && inCustomClass)) {
|
||||
name = c.pkg.join(".") + "." + name;
|
||||
if (c.pkg != null && (inCustomClass != null && inCustomClass)) {
|
||||
name = '${c.pkg.join(".")}.$name';//c.pkg.join(".") + "." + name;
|
||||
}
|
||||
if (as != null) _customClassAliases.set(as, name);
|
||||
_customClasses.set(name, c);
|
||||
#end
|
||||
}
|
||||
@@ -755,6 +762,7 @@ class Interp {
|
||||
return null;
|
||||
}
|
||||
|
||||
// backwards compatibility
|
||||
public static var importRedirects:Map<String, String> = new Map();
|
||||
public static function getImportRedirect(className:String):String {
|
||||
return importRedirects.exists(className) ? importRedirects.get(className) : className;
|
||||
@@ -763,6 +771,8 @@ class Interp {
|
||||
public var localImportRedirects:Map<String, String> = new Map();
|
||||
public function getLocalImportRedirect(className:String):String {
|
||||
var className = className;
|
||||
if (InterpConfig.IMPORT_REDIRECTS.exists(className))
|
||||
className = InterpConfig.IMPORT_REDIRECTS.get(className);
|
||||
if (importRedirects.exists(className))
|
||||
className = importRedirects.get(className);
|
||||
if (localImportRedirects.exists(className))
|
||||
@@ -805,6 +815,8 @@ class Interp {
|
||||
|
||||
if (importBlocklist.contains(realClassName))
|
||||
return null;
|
||||
if (InterpConfig.DISALLOW_IMPORT.contains(realClassName))
|
||||
return null;
|
||||
var cl = Type.resolveClass(realClassName);
|
||||
if (cl == null)
|
||||
cl = Type.resolveClass('${realClassName}_HSC');
|
||||
@@ -1256,11 +1268,12 @@ class Interp {
|
||||
case EUsing(name):
|
||||
useUsing(name);
|
||||
case EEnum(enumName, fields):
|
||||
var obj = {};
|
||||
var obj:HScriptEnum = new HScriptEnum();
|
||||
for (index => field in fields) {
|
||||
switch (field) {
|
||||
case ESimple(name):
|
||||
Reflect.setField(obj, name, new Tools.EnumValue(enumName, name, index, null));
|
||||
//Reflect.setField(obj, name, new Tools.EnumValue(enumName, name, index, obj, null));
|
||||
obj.setEnum(name, new EnumValue(enumName, name, index, obj, null));
|
||||
case EConstructor(name, params):
|
||||
var hasOpt = false, minParams = 0;
|
||||
for (p in params)
|
||||
@@ -1291,11 +1304,12 @@ class Interp {
|
||||
args2.push(args[pos++]);
|
||||
args = args2;
|
||||
}
|
||||
return new Tools.EnumValue(enumName, name, index, args);
|
||||
return new Tools.EnumValue(enumName, name, index, obj, args);
|
||||
};
|
||||
var f = Reflect.makeVarArgs(f);
|
||||
|
||||
Reflect.setField(obj, name, f);
|
||||
//Reflect.setField(obj, name, f);
|
||||
obj.setEnum(name, f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package hscript;
|
||||
|
||||
class InterpConfig {
|
||||
// Automatic import redirect for certain classes
|
||||
public static var IMPORT_REDIRECTS(default, never) = [
|
||||
"Type" => "hscript.proxy.ProxyType"
|
||||
];
|
||||
|
||||
// Incase an import fails
|
||||
// These are the module names
|
||||
@:unreflective public static var DISALLOW_IMPORT(default, never) = [
|
||||
"Type"
|
||||
];
|
||||
}
|
||||
+28
-1
@@ -173,11 +173,13 @@ class EnumValue {
|
||||
public var name: String;
|
||||
public var index: Int;
|
||||
public var args: Array<Dynamic>;
|
||||
public var enumParent:Dynamic;
|
||||
|
||||
public function new(enumName: String, name: String, index: Int, ?args: Array<Dynamic>) {
|
||||
public function new(enumName: String, name: String, index: Int, enumParent:Dynamic, ?args: Array<Dynamic>) {
|
||||
this.enumName = enumName;
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.enumParent = enumParent;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@@ -211,4 +213,29 @@ class EnumValue {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class HScriptEnum implements IHScriptCustomBehaviour{
|
||||
public var enumValues(default, null) = {};
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function setEnum(name:String, enumValue:Dynamic) {
|
||||
//enumValues.set(name, enumValue);
|
||||
Reflect.setField(enumValues, name, enumValue);
|
||||
}
|
||||
|
||||
public function getEnum(name:String):Null<Dynamic> {
|
||||
//if(enumValues.exists(name)) return enumValues.get(name);
|
||||
if(Reflect.hasField(enumValues, name)) return Reflect.field(enumValues, name);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hget(name:String):Dynamic {
|
||||
return getEnum(name);
|
||||
}
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic {
|
||||
throw new haxe.exceptions.NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
package hscript.proxy;
|
||||
|
||||
import hscript.customclass.CustomClass;
|
||||
import hscript.customclass.CustomClassDecl;
|
||||
import hscript.Tools.HScriptEnum;
|
||||
import hscript.Tools.EnumValue as HScriptEnumValue;
|
||||
|
||||
abstract OneOfTwo<T1, T2>(Dynamic) from T1 from T2 to T1 to T2 {}
|
||||
|
||||
class ProxyType {
|
||||
/**
|
||||
Returns the class of `o`, if `o` is a class instance.
|
||||
|
||||
If `o` is null or of a different type, null is returned.
|
||||
|
||||
In general, type parameter information cannot be obtained at runtime.
|
||||
**/
|
||||
inline static function getClass<T>(o:T):Null<Class<T>> {
|
||||
return Type.getClass(o);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the enum of enum instance `o`.
|
||||
|
||||
An enum instance is the result of using an enum constructor. Given an
|
||||
`enum Color { Red; }`, `getEnum(Red)` returns `Enum<Color>`.
|
||||
|
||||
If `o` is null, null is returned.
|
||||
|
||||
In general, type parameter information cannot be obtained at runtime.
|
||||
**/
|
||||
inline static function getEnum(o:OneOfTwo<EnumValue, HScriptEnumValue>):Dynamic {
|
||||
// TODO: SUPPORT HSCRIPT ENUMS
|
||||
var isScripted:Bool = Std.isOfType(o, HScriptEnumValue);
|
||||
if(isScripted) {
|
||||
return cast(o, HScriptEnumValue).enumParent;
|
||||
}
|
||||
return Type.getEnum(cast o);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the super-class of class `c`.
|
||||
|
||||
If `c` has no super class, null is returned.
|
||||
|
||||
If `c` is null, the result is unspecified.
|
||||
|
||||
In general, type parameter information cannot be obtained at runtime.
|
||||
**/
|
||||
inline static function getSuperClass(c:Class<Dynamic>):Class<Dynamic> {
|
||||
return Type.getSuperClass(c);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the name of class `c`, including its path.
|
||||
|
||||
If `c` is inside a package, the package structure is returned dot-
|
||||
separated, with another dot separating the class name:
|
||||
`pack1.pack2.(...).packN.ClassName`
|
||||
If `c` is a sub-type of a Haxe module, that module is not part of the
|
||||
package structure.
|
||||
|
||||
If `c` has no package, the class name is returned.
|
||||
|
||||
If `c` is null, the result is unspecified.
|
||||
|
||||
The class name does not include any type parameters.
|
||||
**/
|
||||
inline static function getClassName(c:Class<Dynamic>):String {
|
||||
return Type.getClassName(c);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the name of enum `e`, including its path.
|
||||
|
||||
If `e` is inside a package, the package structure is returned dot-
|
||||
separated, with another dot separating the enum name:
|
||||
`pack1.pack2.(...).packN.EnumName`
|
||||
If `e` is a sub-type of a Haxe module, that module is not part of the
|
||||
package structure.
|
||||
|
||||
If `e` has no package, the enum name is returned.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
|
||||
The enum name does not include any type parameters.
|
||||
**/
|
||||
inline static function getEnumName(e:Enum<Dynamic>):String {
|
||||
var isScripted:Bool = Std.isOfType(e, HScriptEnumValue);
|
||||
if (isScripted)
|
||||
return cast(e, HScriptEnumValue).getEnumName();
|
||||
return Type.getEnumName(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Resolves a class by name.
|
||||
|
||||
If `name` is the path of an existing class, that class is returned.
|
||||
|
||||
Otherwise null is returned.
|
||||
|
||||
If `name` is null or the path to a different type, the result is
|
||||
unspecified.
|
||||
|
||||
The class name must not include any type parameters.
|
||||
**/
|
||||
inline static function resolveClass(name:String):Dynamic {
|
||||
// Dynamic to no mess with casting
|
||||
if(Interp.customClassExist(name)) {
|
||||
return Interp.getCustomClass(name);
|
||||
}
|
||||
return Type.resolveClass(name);
|
||||
}
|
||||
|
||||
/**
|
||||
Resolves an enum by name.
|
||||
|
||||
If `name` is the path of an existing enum, that enum is returned.
|
||||
|
||||
Otherwise null is returned.
|
||||
|
||||
If `name` is null the result is unspecified.
|
||||
|
||||
If `name` is the path to a different type, null is returned.
|
||||
|
||||
The enum name must not include any type parameters.
|
||||
**/
|
||||
inline static function resolveEnum(name:String):Enum<Dynamic> {
|
||||
return Type.resolveEnum(name);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an instance of class `cl`, using `args` as arguments to the
|
||||
class constructor.
|
||||
|
||||
This function guarantees that the class constructor is called.
|
||||
|
||||
Default values of constructors arguments are not guaranteed to be
|
||||
taken into account.
|
||||
|
||||
If `cl` or `args` are null, or if the number of elements in `args` does
|
||||
not match the expected number of constructor arguments, or if any
|
||||
argument has an invalid type, or if `cl` has no own constructor, the
|
||||
result is unspecified.
|
||||
|
||||
In particular, default values of constructor arguments are not
|
||||
guaranteed to be taken into account.
|
||||
**/
|
||||
inline static function createInstance<T>(cl:OneOfTwo<Class<T>, CustomClassDecl>, args:Array<Dynamic>):T {
|
||||
if(cl is CustomClassDecl) {
|
||||
//return cast new CustomClass(cast cl, args);
|
||||
return cast Type.createInstance(CustomClass, [cast cl, args]);
|
||||
}
|
||||
return Type.createInstance(cast cl, args);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an instance of class `cl`.
|
||||
|
||||
This function guarantees that the class constructor is not called.
|
||||
|
||||
If `cl` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function createEmptyInstance<T>(cl:Class<T>):T {
|
||||
return Type.createEmptyInstance(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an instance of enum `e` by calling its constructor `constr` with
|
||||
arguments `params`.
|
||||
|
||||
If `e` or `constr` is null, or if enum `e` has no constructor named
|
||||
`constr`, or if the number of elements in `params` does not match the
|
||||
expected number of constructor arguments, or if any argument has an
|
||||
invalid type, the result is unspecified.
|
||||
**/
|
||||
inline static function createEnum<T>(e:OneOfTwo<Enum<T>, HScriptEnum>, constr:String, ?params:Array<Dynamic>):T {
|
||||
// TODO: SUPPORT HSCRIPT ENUMS
|
||||
var isScripted:Bool = Std.isOfType(e, HScriptEnum);
|
||||
if(isScripted) {
|
||||
var scriptEnum:HScriptEnum = cast e;
|
||||
var enumToCreate = scriptEnum.getEnum(constr);
|
||||
if(Reflect.isFunction(enumToCreate)) {
|
||||
return Reflect.callMethod(null, enumToCreate, params);
|
||||
}
|
||||
return enumToCreate;
|
||||
}
|
||||
return Type.createEnum(cast e, constr, params);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an instance of enum `e` by calling its constructor number
|
||||
`index` with arguments `params`.
|
||||
|
||||
The constructor indices are preserved from Haxe syntax, so the first
|
||||
declared is index 0, the next index 1 etc.
|
||||
|
||||
If `e` or `constr` is null, or if enum `e` has no constructor named
|
||||
`constr`, or if the number of elements in `params` does not match the
|
||||
expected number of constructor arguments, or if any argument has an
|
||||
invalid type, the result is unspecified.
|
||||
**/
|
||||
inline static function createEnumIndex<T>(e:Enum<T>, index:Int, ?params:Array<Dynamic>):T {
|
||||
// TODO: SUPPORT HSCRIPT ENUMS
|
||||
return Type.createEnumIndex(e, index, params);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a list of the instance fields of class `c`, including
|
||||
inherited fields.
|
||||
|
||||
This only includes fields which are known at compile-time. In
|
||||
particular, using `getInstanceFields(getClass(obj))` will not include
|
||||
any fields which were added to `obj` at runtime.
|
||||
|
||||
The order of the fields in the returned Array is unspecified.
|
||||
|
||||
If `c` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function getInstanceFields(c:Class<Dynamic>):Array<String> {
|
||||
return Type.getInstanceFields(c);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a list of static fields of class `c`.
|
||||
|
||||
This does not include static fields of parent classes.
|
||||
|
||||
The order of the fields in the returned Array is unspecified.
|
||||
|
||||
If `c` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function getClassFields(c:Class<Dynamic>):Array<String> {
|
||||
return Type.getClassFields(c);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a list of the names of all constructors of enum `e`.
|
||||
|
||||
The order of the constructor names in the returned Array is preserved
|
||||
from the original syntax.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function getEnumConstructs(e:OneOfTwo<Enum<Dynamic>, HScriptEnum>):Array<String> {
|
||||
// TODO: SUPPORT HSCRIPT ENUMS
|
||||
return Type.getEnumConstructs(cast e);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the runtime type of value `v`.
|
||||
|
||||
The result corresponds to the type `v` has at runtime, which may vary
|
||||
per platform. Assumptions regarding this should be minimized to avoid
|
||||
surprises.
|
||||
**/
|
||||
inline static function typeof(v:Dynamic):Type.ValueType {
|
||||
return Type.typeof(v);
|
||||
}
|
||||
|
||||
/**
|
||||
Recursively compares two enum instances `a` and `b` by value.
|
||||
|
||||
Unlike `a == b`, this function performs a deep equality check on the
|
||||
arguments of the constructors, if exists.
|
||||
|
||||
If `a` or `b` are null, the result is unspecified.
|
||||
**/
|
||||
inline static function enumEq(a:Dynamic, b:Dynamic):Bool {
|
||||
var isScripted:Bool = Std.isOfType(a, HScriptEnumValue) && Std.isOfType(b, HScriptEnumValue);
|
||||
if (isScripted)
|
||||
return cast(a, HScriptEnumValue).compare(cast(b, HScriptEnumValue));
|
||||
return Type.enumEq(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the constructor name of enum instance `e`.
|
||||
|
||||
The result String does not contain any constructor arguments.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function enumConstructor(e:Dynamic):String {
|
||||
if (Std.isOfType(e, HScriptEnumValue))
|
||||
return cast(e, HScriptEnumValue).name;
|
||||
return Type.enumConstructor(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a list of the constructor arguments of enum instance `e`.
|
||||
|
||||
If `e` has no arguments, the result is [].
|
||||
|
||||
Otherwise the result are the values that were used as arguments to `e`,
|
||||
in the order of their declaration.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function enumParameters(e:Dynamic):Array<Dynamic> {
|
||||
if (Std.isOfType(e, HScriptEnumValue))
|
||||
return cast(e, HScriptEnumValue).args;
|
||||
return Type.enumParameters(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the index of enum instance `e`.
|
||||
|
||||
This corresponds to the original syntactic position of `e`. The index of
|
||||
the first declared constructor is 0, the next one is 1 etc.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function enumIndex(e:Dynamic):Int {
|
||||
if (Std.isOfType(e, HScriptEnumValue))
|
||||
return cast(e, HScriptEnumValue).index;
|
||||
return Type.enumIndex(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a list of all constructors of enum `e` that require no
|
||||
arguments.
|
||||
|
||||
This may return the empty Array `[]` if all constructors of `e` require
|
||||
arguments.
|
||||
|
||||
Otherwise an instance of `e` constructed through each of its non-
|
||||
argument constructors is returned, in the order of the constructor
|
||||
declaration.
|
||||
|
||||
If `e` is null, the result is unspecified.
|
||||
**/
|
||||
inline static function allEnums<T>(e:Enum<T>):Array<T> {
|
||||
// TODO: SUPPORT HSCRIPT ENUMS
|
||||
var isScripted:Bool = Std.isOfType(e, HScriptEnum);
|
||||
if(isScripted) {
|
||||
var hEnum:HScriptEnum = cast e;
|
||||
return [for(en in Reflect.fields(hEnum.enumValues)) Reflect.field(hEnum, en)];
|
||||
}
|
||||
return Type.allEnums(e);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user