Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49c90e6434 | ||
|
|
bb46d45d56 | ||
|
|
3a5c4f2164 | ||
|
|
f18c7a2210 | ||
|
|
123a7de64a | ||
|
|
e0e1436930 | ||
|
|
b96e6c8149 | ||
|
|
f6402ac638 | ||
|
|
1e55d0200b | ||
|
|
1725dfd1ea | ||
|
|
a8cc0ccc86 | ||
|
|
7dd868aac7 | ||
|
|
220e5ce007 | ||
|
|
80f6ea4502 | ||
|
|
eb820aaf6a | ||
|
|
a754c162d9 | ||
|
|
de18ceb887 |
@@ -1,2 +1,4 @@
|
|||||||
/hscript.swf
|
/hscript.swf
|
||||||
/release.zip
|
/release.zip
|
||||||
|
|
||||||
|
tests/bin/*
|
||||||
@@ -1,8 +1,18 @@
|
|||||||
hscript
|
hscript-improved
|
||||||
=======
|
=======
|
||||||
|
|
||||||
[](https://travis-ci.org/HaxeFoundation/hscript)
|
How to install
|
||||||
[](https://ci.appveyor.com/project/HaxeFoundation/hscript)
|
```
|
||||||
|
haxelib git hscript-improved https://github.com/FNF-CNE-Devs/hscript-improved.git
|
||||||
|
```
|
||||||
|
|
||||||
|
To enable custom classes support you have to do this in project.xml
|
||||||
|
```xml
|
||||||
|
<define name="CUSTOM_CLASSES" />
|
||||||
|
```
|
||||||
|
Warning: custom classes are sometimes broken, would like help to fix them. You can only override functions from the current class, not from the extended part, like you cant override update in FlxText because FlxText doesnt have a update function overriden
|
||||||
|
|
||||||
|
-----------
|
||||||
|
|
||||||
Parse and evalutate Haxe expressions.
|
Parse and evalutate Haxe expressions.
|
||||||
|
|
||||||
@@ -100,4 +110,4 @@ Some other optional files :
|
|||||||
- `hscript.Macro` : convert Haxe macro into hscript Expr
|
- `hscript.Macro` : convert Haxe macro into hscript Expr
|
||||||
- `hscript.Printer` : convert hscript Expr to String
|
- `hscript.Printer` : convert hscript Expr to String
|
||||||
- `hscript.Tools` : utility functions (map/iter)
|
- `hscript.Tools` : utility functions (map/iter)
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -1,2 +1,3 @@
|
|||||||
--macro keep('IntIterator')
|
--macro keep('IntIterator')
|
||||||
--macro hscript.UsingHandler.init()
|
--macro hscript.macros.UsingHandler.init()
|
||||||
|
--macro hscript.macros.ClassExtendMacro.init()
|
||||||
|
|||||||
+2
-1
@@ -1233,9 +1233,10 @@ class Checker {
|
|||||||
mergeType( typeExpr(defaultExpr, withType), defaultExpr);
|
mergeType( typeExpr(defaultExpr, withType), defaultExpr);
|
||||||
return withType == NoValue ? TVoid : tmin == null ? makeMono() : tmin;
|
return withType == NoValue ? TVoid : tmin == null ? makeMono() : tmin;
|
||||||
case ENew(cl, params):
|
case ENew(cl, params):
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
error("Don't know how to type "+edef(expr).getName(), expr);
|
error("Don't know how to type "+edef(expr).getName(), expr);
|
||||||
return TDynamic;
|
return TDynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package hscript;
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
// Runs support for custom classes in these
|
||||||
|
public static final ALLOWED_CUSTOM_CLASSES = [
|
||||||
|
"flixel",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Runs support for abstract support in these
|
||||||
|
public static final ALLOWED_ABSTRACT_AND_ENUM = [
|
||||||
|
"flixel",
|
||||||
|
"openfl.display.BlendMode",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Incase any of your files fail
|
||||||
|
// These are the module names
|
||||||
|
public static final DISALLOW_CUSTOM_CLASSES = [
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
public static final DISALLOW_ABSTRACT_AND_ENUM = [
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -25,6 +25,9 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
interp.errorHandler = ogInterp.errorHandler;
|
interp.errorHandler = ogInterp.errorHandler;
|
||||||
|
|
||||||
var cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
|
var cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
|
||||||
|
if(cl == null)
|
||||||
|
ogInterp.error(EInvalidClass(extend));
|
||||||
|
|
||||||
var _class = Type.createInstance(cl, args);
|
var _class = Type.createInstance(cl, args);
|
||||||
|
|
||||||
var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
|
var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
|
||||||
@@ -35,18 +38,14 @@ class CustomClassHandler implements IHScriptCustomConstructor {
|
|||||||
|
|
||||||
var disallowCopy = Type.getInstanceFields(cl);
|
var disallowCopy = Type.getInstanceFields(cl);
|
||||||
|
|
||||||
//trace("Locals");
|
|
||||||
for (key => value in capturedLocals) {
|
for (key => value in capturedLocals) {
|
||||||
if(!disallowCopy.contains(key)) {
|
if(!disallowCopy.contains(key)) {
|
||||||
interp.locals.set(key, {r: value, depth: -1});
|
interp.locals.set(key, {r: value, depth: -1});
|
||||||
//trace(key, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//trace("Variables");
|
|
||||||
for (key => value in ogInterp.variables) {
|
for (key => value in ogInterp.variables) {
|
||||||
if(!disallowCopy.contains(key)) {
|
if(!disallowCopy.contains(key)) {
|
||||||
interp.variables.set(key, value);
|
interp.variables.set(key, value);
|
||||||
//trace(key, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ enum Expr {
|
|||||||
ECall( e : Expr, params : Array<Expr> );
|
ECall( e : Expr, params : Array<Expr> );
|
||||||
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||||
EWhile( cond : Expr, e : Expr );
|
EWhile( cond : Expr, e : Expr );
|
||||||
EFor( v : String, it : Expr, e : Expr );
|
EFor( v : String, it : Expr, e : Expr, ?ithv: String);
|
||||||
EBreak;
|
EBreak;
|
||||||
EContinue;
|
EContinue;
|
||||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||||
|
|||||||
+80
-19
@@ -160,6 +160,7 @@ class Interp {
|
|||||||
binops.set("<", function(e1, e2) return me.expr(e1) < me.expr(e2));
|
binops.set("<", function(e1, e2) return me.expr(e1) < me.expr(e2));
|
||||||
binops.set("||", function(e1, e2) return me.expr(e1) == true || me.expr(e2) == true);
|
binops.set("||", function(e1, e2) return me.expr(e1) == true || me.expr(e2) == true);
|
||||||
binops.set("&&", function(e1, e2) return me.expr(e1) == true && me.expr(e2) == true);
|
binops.set("&&", function(e1, e2) return me.expr(e1) == true && me.expr(e2) == true);
|
||||||
|
binops.set("is", checkIsType);
|
||||||
binops.set("=", assign);
|
binops.set("=", assign);
|
||||||
binops.set("??", function(e1, e2) {
|
binops.set("??", function(e1, e2) {
|
||||||
var expr1:Dynamic = me.expr(e1);
|
var expr1:Dynamic = me.expr(e1);
|
||||||
@@ -182,11 +183,25 @@ class Interp {
|
|||||||
assignOp("<<=", function(v1, v2) return v1 << v2);
|
assignOp("<<=", function(v1, v2) return v1 << v2);
|
||||||
assignOp(">>=", function(v1, v2) return v1 >> v2);
|
assignOp(">>=", function(v1, v2) return v1 >> v2);
|
||||||
assignOp(">>>=", function(v1, v2) return v1 >>> v2);
|
assignOp(">>>=", function(v1, v2) return v1 >>> v2);
|
||||||
assignOp("is", function(v1, v2) return Std.isOfType(v1, v2));
|
assignOp("??" + "=", function(v1, v2) return v1 == null ? v2 : v1);
|
||||||
assignOp("??=", function(v1, v2) return v1 == null ? v2 : v1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVar(name:String, v:Dynamic) {
|
function checkIsType(e1,e2): Bool {
|
||||||
|
var expr1:Dynamic = expr(e1);
|
||||||
|
|
||||||
|
return switch(Tools.expr(e2))
|
||||||
|
{
|
||||||
|
case EIdent("Class"):
|
||||||
|
Std.isOfType(expr1, Class);
|
||||||
|
case EIdent("Map") | EIdent("IMap"):
|
||||||
|
Std.isOfType(expr1, IMap);
|
||||||
|
default:
|
||||||
|
var expr2:Dynamic = expr(e2);
|
||||||
|
expr2 != null ? Std.isOfType(expr1, expr2) : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setVar(name:String, v:Dynamic) {
|
||||||
if (allowStaticVariables && staticVariables.exists(name))
|
if (allowStaticVariables && staticVariables.exists(name))
|
||||||
staticVariables.set(name, v);
|
staticVariables.set(name, v);
|
||||||
else if (allowPublicVariables && publicVariables.exists(name))
|
else if (allowPublicVariables && publicVariables.exists(name))
|
||||||
@@ -229,8 +244,10 @@ class Interp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO
|
// TODO
|
||||||
case EField(e, f):
|
case EField(e, f, s):
|
||||||
v = set(expr(e), f, v);
|
var obj = expr(e);
|
||||||
|
if(s && obj == null) return null;
|
||||||
|
v = set(obj, f, v);
|
||||||
case EArray(e, index):
|
case EArray(e, index):
|
||||||
var arr:Dynamic = expr(e);
|
var arr:Dynamic = expr(e);
|
||||||
var index:Dynamic = expr(index);
|
var index:Dynamic = expr(index);
|
||||||
@@ -268,8 +285,9 @@ class Interp {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
l.r = v;
|
l.r = v;
|
||||||
case EField(e, f):
|
case EField(e, f, s):
|
||||||
var obj = expr(e);
|
var obj = expr(e);
|
||||||
|
if(s && obj == null) return null;
|
||||||
v = fop(get(obj, f), expr(e2));
|
v = fop(get(obj, f), expr(e2));
|
||||||
v = set(obj, f, v);
|
v = set(obj, f, v);
|
||||||
case EArray(e, index):
|
case EArray(e, index):
|
||||||
@@ -308,8 +326,9 @@ class Interp {
|
|||||||
else
|
else
|
||||||
l.r = v + delta;
|
l.r = v + delta;
|
||||||
return v;
|
return v;
|
||||||
case EField(e, f):
|
case EField(e, f, s):
|
||||||
var obj = expr(e);
|
var obj = expr(e);
|
||||||
|
if(s && obj == null) return null;
|
||||||
var v:Dynamic = get(obj, f);
|
var v:Dynamic = get(obj, f);
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
v += delta;
|
v += delta;
|
||||||
@@ -403,7 +422,7 @@ class Interp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function error(e:#if hscriptPos ErrorDef #else Error #end, rethrow = false):Dynamic {
|
public inline function error(e:#if hscriptPos ErrorDef #else Error #end, rethrow = false):Dynamic {
|
||||||
#if hscriptPos var e = new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line); #end
|
#if hscriptPos var e = new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line); #end
|
||||||
|
|
||||||
if (rethrow) {
|
if (rethrow) {
|
||||||
@@ -423,6 +442,8 @@ class Interp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function resolve(id:String, doException:Bool = true):Dynamic {
|
public function resolve(id:String, doException:Bool = true):Dynamic {
|
||||||
|
if (id == null)
|
||||||
|
return null;
|
||||||
id = StringTools.trim(id);
|
id = StringTools.trim(id);
|
||||||
var l = locals.get(id);
|
var l = locals.get(id);
|
||||||
if (l != null)
|
if (l != null)
|
||||||
@@ -452,6 +473,21 @@ class Interp {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static var importRedirects:Map<String, String> = new Map();
|
||||||
|
public static function getImportRedirect(className:String):String {
|
||||||
|
return importRedirects.exists(className) ? importRedirects.get(className) : className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public var localImportRedirects:Map<String, String> = new Map();
|
||||||
|
public function getLocalImportRedirect(className:String):String {
|
||||||
|
var className = className;
|
||||||
|
if (importRedirects.exists(className))
|
||||||
|
className = importRedirects.get(className);
|
||||||
|
if (localImportRedirects.exists(className))
|
||||||
|
className = localImportRedirects.get(className);
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
public function expr(e:Expr):Dynamic {
|
public function expr(e:Expr):Dynamic {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
curExpr = e;
|
curExpr = e;
|
||||||
@@ -461,7 +497,14 @@ class Interp {
|
|||||||
case EClass(name, fields, extend, interfaces):
|
case EClass(name, fields, extend, interfaces):
|
||||||
if (customClasses.exists(name))
|
if (customClasses.exists(name))
|
||||||
error(EAlreadyExistingClass(name));
|
error(EAlreadyExistingClass(name));
|
||||||
customClasses.set(name, new CustomClassHandler(this, name, fields, extend, interfaces));
|
|
||||||
|
inline function importVar(thing:String):String {
|
||||||
|
if (thing == null)
|
||||||
|
return null;
|
||||||
|
final variable:Class<Any> = variables.exists(thing) ? cast variables.get(thing) : null;
|
||||||
|
return variable == null ? thing : Type.getClassName(variable);
|
||||||
|
}
|
||||||
|
customClasses.set(name, new CustomClassHandler(this, name, fields, importVar(extend), [for (i in interfaces) importVar(i)]));
|
||||||
case EImport(c, n):
|
case EImport(c, n):
|
||||||
if (!importEnabled)
|
if (!importEnabled)
|
||||||
return null;
|
return null;
|
||||||
@@ -475,6 +518,8 @@ class Interp {
|
|||||||
if (variables.exists(toSetName)) // class is already imported
|
if (variables.exists(toSetName)) // class is already imported
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
var realClassName = getLocalImportRedirect(realClassName);
|
||||||
|
|
||||||
if (importBlocklist.contains(realClassName))
|
if (importBlocklist.contains(realClassName))
|
||||||
return null;
|
return null;
|
||||||
var cl = Type.resolveClass(realClassName);
|
var cl = Type.resolveClass(realClassName);
|
||||||
@@ -491,6 +536,8 @@ class Interp {
|
|||||||
splitClassName.splice(-2, 1); // Remove the last last item
|
splitClassName.splice(-2, 1); // Remove the last last item
|
||||||
realClassName = splitClassName.join(".");
|
realClassName = splitClassName.join(".");
|
||||||
|
|
||||||
|
var realClassName = getLocalImportRedirect(realClassName);
|
||||||
|
|
||||||
if (importBlocklist.contains(realClassName))
|
if (importBlocklist.contains(realClassName))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -616,8 +663,8 @@ class Interp {
|
|||||||
case EDoWhile(econd, e):
|
case EDoWhile(econd, e):
|
||||||
doWhileLoop(econd, e);
|
doWhileLoop(econd, e);
|
||||||
return null;
|
return null;
|
||||||
case EFor(v, it, e):
|
case EFor(v, it, e, ithv):
|
||||||
forLoop(v, it, e);
|
forLoop(v, it, e, ithv);
|
||||||
return null;
|
return null;
|
||||||
case EBreak:
|
case EBreak:
|
||||||
throw SBreak;
|
throw SBreak;
|
||||||
@@ -888,26 +935,40 @@ class Interp {
|
|||||||
restore(old);
|
restore(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeIterator(v:Dynamic):Iterator<Dynamic> {
|
function makeIterator(v:Dynamic, ?allowKeyValue = false):Iterator<Dynamic> {
|
||||||
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
|
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
|
||||||
if (v.iterator != null)
|
if (v.iterator != null)
|
||||||
v = v.iterator();
|
v = v.iterator();
|
||||||
#else
|
#else
|
||||||
try
|
if(allowKeyValue) {
|
||||||
v = v.iterator()
|
try
|
||||||
catch (e:Dynamic) {};
|
v = v.keyValueIterator()
|
||||||
|
catch (e:Dynamic) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(v.hasNext == null || v.next == null) {
|
||||||
|
try
|
||||||
|
v = v.iterator()
|
||||||
|
catch (e:Dynamic) {};
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
if (v.hasNext == null || v.next == null)
|
if (v.hasNext == null || v.next == null)
|
||||||
error(EInvalidIterator(v));
|
error(EInvalidIterator(v));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
function forLoop(n, it, e) {
|
function forLoop(n, it, e, ?ithv) {
|
||||||
|
var isKeyValue = ithv != null;
|
||||||
var old = declared.length;
|
var old = declared.length;
|
||||||
|
if(isKeyValue)
|
||||||
|
declared.push({n: ithv, old: locals.get(ithv), depth: depth});
|
||||||
declared.push({n: n, old: locals.get(n), depth: depth});
|
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||||
var it = makeIterator(expr(it));
|
var it = makeIterator(expr(it), isKeyValue);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
locals.set(n, {r: it.next(), depth: depth});
|
var next = it.next();
|
||||||
|
if(isKeyValue)
|
||||||
|
locals.set(ithv, {r: next.key, depth: depth});
|
||||||
|
locals.set(n, {r: isKeyValue ? next.value : next, depth: depth});
|
||||||
try {
|
try {
|
||||||
expr(e);
|
expr(e);
|
||||||
} catch (err:Stop) {
|
} catch (err:Stop) {
|
||||||
@@ -1020,4 +1081,4 @@ class Interp {
|
|||||||
c = Type.resolveClass(cl);
|
c = Type.resolveClass(cl);
|
||||||
return (c is IHScriptCustomConstructor) ? cast(c, IHScriptCustomConstructor).hnew(args) : Type.createInstance(c, args);
|
return (c is IHScriptCustomConstructor) ? cast(c, IHScriptCustomConstructor).hnew(args) : Type.createInstance(c, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,6 +252,8 @@ class Macro {
|
|||||||
EMeta({ name : m, params : params == null ? [] : [for( p in params ) convert(p)], pos : mpos }, convert(esub));
|
EMeta({ name : m, params : params == null ? [] : [for( p in params ) convert(p)], pos : mpos }, convert(esub));
|
||||||
case ECheckType(e, t):
|
case ECheckType(e, t):
|
||||||
ECheckType(convert(e), convertType(t));
|
ECheckType(convert(e), convertType(t));
|
||||||
|
default:
|
||||||
|
null;
|
||||||
}, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end }
|
}, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+29
-10
@@ -60,10 +60,10 @@ class Parser {
|
|||||||
/**
|
/**
|
||||||
allows to check for #if / #else in code
|
allows to check for #if / #else in code
|
||||||
**/
|
**/
|
||||||
public var preprocesorValues : Map<String,Dynamic> = new Map();
|
public var preprocessorValues : Map<String,Dynamic> = new Map();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
activate JSON compatiblity
|
activate JSON compatibility
|
||||||
**/
|
**/
|
||||||
public var allowJSON : Bool;
|
public var allowJSON : Bool;
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ class Parser {
|
|||||||
["..."],
|
["..."],
|
||||||
["&&"],
|
["&&"],
|
||||||
["||"],
|
["||"],
|
||||||
["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^=","=>","??="],
|
["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^=","=>","??" + "="],
|
||||||
["->", "??"],
|
["->", "??"],
|
||||||
["is"]
|
["is"]
|
||||||
];
|
];
|
||||||
@@ -185,6 +185,7 @@ class Parser {
|
|||||||
|
|
||||||
public function parseString( s : String, ?origin : String = "hscript" ) {
|
public function parseString( s : String, ?origin : String = "hscript" ) {
|
||||||
initParser(origin);
|
initParser(origin);
|
||||||
|
if(s == "") s = "0;"; // fixing crash with empty file
|
||||||
input = s;
|
input = s;
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
var a = new Array();
|
var a = new Array();
|
||||||
@@ -547,8 +548,8 @@ class Parser {
|
|||||||
function mapCompr( tmp : String, e : Expr ) {
|
function mapCompr( tmp : String, e : Expr ) {
|
||||||
if( e == null ) return null;
|
if( e == null ) return null;
|
||||||
var edef = switch( expr(e) ) {
|
var edef = switch( expr(e) ) {
|
||||||
case EFor(v, it, e2):
|
case EFor(v, it, e2, ithv):
|
||||||
EFor(v, it, mapCompr(tmp, e2));
|
EFor(v, it, mapCompr(tmp, e2), ithv);
|
||||||
case EWhile(cond, e2):
|
case EWhile(cond, e2):
|
||||||
EWhile(cond, mapCompr(tmp, e2));
|
EWhile(cond, mapCompr(tmp, e2));
|
||||||
case EDoWhile(cond, e2):
|
case EDoWhile(cond, e2):
|
||||||
@@ -743,12 +744,21 @@ class Parser {
|
|||||||
mk(EDoWhile(econd,e),p1,pmax(econd));
|
mk(EDoWhile(econd,e),p1,pmax(econd));
|
||||||
case "for":
|
case "for":
|
||||||
ensure(TPOpen);
|
ensure(TPOpen);
|
||||||
|
var ithv:String = null;
|
||||||
var vname = getIdent();
|
var vname = getIdent();
|
||||||
|
var tk = token();
|
||||||
|
if( Type.enumEq(tk,TOp("=>")) ) {
|
||||||
|
var old = vname;
|
||||||
|
vname = getIdent();
|
||||||
|
ithv = old;
|
||||||
|
} else {
|
||||||
|
push(tk);
|
||||||
|
}
|
||||||
ensureToken(TId("in"));
|
ensureToken(TId("in"));
|
||||||
var eiter = parseExpr();
|
var eiter = parseExpr();
|
||||||
ensure(TPClose);
|
ensure(TPClose);
|
||||||
var e = parseExpr();
|
var e = parseExpr();
|
||||||
mk(EFor(vname,eiter,e),p1,pmax(e));
|
mk(EFor(vname,eiter,e,ithv),p1,pmax(e));
|
||||||
case "break": mk(EBreak);
|
case "break": mk(EBreak);
|
||||||
case "continue": mk(EContinue);
|
case "continue": mk(EContinue);
|
||||||
case "else": unexpected(TId(id));
|
case "else": unexpected(TId(id));
|
||||||
@@ -1805,7 +1815,7 @@ class Parser {
|
|||||||
case '?'.code:
|
case '?'.code:
|
||||||
var orp = readPos;
|
var orp = readPos;
|
||||||
if (readChar() == '='.code)
|
if (readChar() == '='.code)
|
||||||
return TOp("??=");
|
return TOp("??" + "=");
|
||||||
|
|
||||||
this.readPos = orp;
|
this.readPos = orp;
|
||||||
return TOp("??");
|
return TOp("??");
|
||||||
@@ -1879,6 +1889,7 @@ class Parser {
|
|||||||
if( StringTools.isEof(char) ) char = 0;
|
if( StringTools.isEof(char) ) char = 0;
|
||||||
if( !idents[char] ) {
|
if( !idents[char] ) {
|
||||||
this.char = char;
|
this.char = char;
|
||||||
|
if(id == "is") return TOp("is");
|
||||||
return TId(id);
|
return TId(id);
|
||||||
}
|
}
|
||||||
id += String.fromCharCode(char);
|
id += String.fromCharCode(char);
|
||||||
@@ -1992,9 +2003,14 @@ class Parser {
|
|||||||
var pos = readPos;
|
var pos = readPos;
|
||||||
while( true ) {
|
while( true ) {
|
||||||
var tk = token();
|
var tk = token();
|
||||||
// TODO: Fix ending in with #end in the file
|
|
||||||
if( tk == TEof )
|
if( tk == TEof ) {
|
||||||
error(EInvalidPreprocessor("Unclosed"), pos, pos);
|
if (preprocStack.length != 0) {
|
||||||
|
error(EInvalidPreprocessor("Unclosed"), pos, pos);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if( preprocStack[spos] != obj ) {
|
if( preprocStack[spos] != obj ) {
|
||||||
push(tk);
|
push(tk);
|
||||||
break;
|
break;
|
||||||
@@ -2078,4 +2094,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@:noCompletion public var preprocesorValues(get,set) : Map<String,Dynamic>;
|
||||||
|
inline function get_preprocesorValues() return this.preprocessorValues;
|
||||||
|
inline function set_preprocesorValues(v) return this.preprocessorValues = v;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -217,8 +217,11 @@ class Printer {
|
|||||||
add(" while ( ");
|
add(" while ( ");
|
||||||
expr(cond);
|
expr(cond);
|
||||||
add(" )");
|
add(" )");
|
||||||
case EFor(v, it, e):
|
case EFor(v, it, e, ithv):
|
||||||
add("for( "+v+" in ");
|
if(ithv != null)
|
||||||
|
add("for( "+ithv+" => "+v+" in ");
|
||||||
|
else
|
||||||
|
add("for( "+v+" in ");
|
||||||
expr(it);
|
expr(it);
|
||||||
add(" ) ");
|
add(" ) ");
|
||||||
expr(e);
|
expr(e);
|
||||||
|
|||||||
@@ -0,0 +1,437 @@
|
|||||||
|
package hscript.macros;
|
||||||
|
|
||||||
|
#if macro
|
||||||
|
import haxe.macro.Type.ClassType;
|
||||||
|
import Type.ValueType;
|
||||||
|
import haxe.macro.Expr.Function;
|
||||||
|
import haxe.macro.Expr;
|
||||||
|
import haxe.macro.Type.MetaAccess;
|
||||||
|
import haxe.macro.Type.FieldKind;
|
||||||
|
import haxe.macro.Type.ClassField;
|
||||||
|
import haxe.macro.Type.VarAccess;
|
||||||
|
import haxe.macro.*;
|
||||||
|
import Sys;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class ClassExtendMacro {
|
||||||
|
public static inline final FUNC_PREFIX = "_HX_SUPER__";
|
||||||
|
public static inline final CLASS_SUFFIX = "_HSX";
|
||||||
|
|
||||||
|
public static var unallowedMetas:Array<String> = [":bitmap", ":noCustomClass", ":generic"];
|
||||||
|
|
||||||
|
public static var modifiedClasses:Array<String> = [];
|
||||||
|
|
||||||
|
public static function init() {
|
||||||
|
#if !display
|
||||||
|
#if CUSTOM_CLASSES
|
||||||
|
if(Context.defined("display")) return;
|
||||||
|
for(apply in Config.ALLOWED_CUSTOM_CLASSES) {
|
||||||
|
Compiler.addGlobalMetadata(apply, "@:build(hscript.macros.ClassExtendMacro.build())");
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function build():Array<Field> {
|
||||||
|
var fields = Context.getBuildFields();
|
||||||
|
var clRef = Context.getLocalClass();
|
||||||
|
if (clRef == null) return fields;
|
||||||
|
var cl = clRef.get();
|
||||||
|
|
||||||
|
if (cl.isAbstract || cl.isExtern || cl.isFinal || cl.isInterface) return fields;
|
||||||
|
if (!cl.name.endsWith("_Impl_") && !cl.name.endsWith(CLASS_SUFFIX) && !cl.name.endsWith("_HSC")) {
|
||||||
|
var metas = cl.meta.get();
|
||||||
|
|
||||||
|
for(m in metas)
|
||||||
|
if (unallowedMetas.contains(m.name))
|
||||||
|
return fields;
|
||||||
|
|
||||||
|
if(cl.params.length > 0)
|
||||||
|
return fields;
|
||||||
|
|
||||||
|
var key = cl.module;
|
||||||
|
var fkey = cl.module + "." + cl.name;
|
||||||
|
if(key == "sys.thread.FixedThreadPool") return fields; // Error: Type name sys.thread.Worker_HSX is redefined from module sys.thread.FixedThreadPool
|
||||||
|
if(key == "StdTypes") return fields; // Error: Cant extend basic class
|
||||||
|
if(key == "Xml") return fields; // Error: Cant extend basic class
|
||||||
|
if(key == "Date") return fields; // Error: Cant extend basic class
|
||||||
|
if(key == "away3d.tools.commands.Mirror") return fields; // Error: Unknown identifier
|
||||||
|
if(key == "away3d.tools.commands.SphereMaker") return fields; // Error: Unknown identifier
|
||||||
|
if(key == "away3d.tools.commands.Weld") return fields; // Error: Unknown identifier
|
||||||
|
if(fkey == "hscript.CustomClassHandler.TemplateClass") return fields; // Error: Redefined
|
||||||
|
if(key == "sys.thread.EventLoop") return fields; // Error: cant override force inlined
|
||||||
|
if(Config.DISALLOW_CUSTOM_CLASSES.contains(cl.module) || Config.DISALLOW_CUSTOM_CLASSES.contains(fkey)) return fields;
|
||||||
|
if(cl.module.contains("_")) return fields; // Weird issue, sorry
|
||||||
|
|
||||||
|
var superFields = [];
|
||||||
|
if(cl.superClass != null) {
|
||||||
|
var _superFields = cl.superClass.t.get().fields.get();
|
||||||
|
_superFields = []; // Comment to enable super support, (broken)
|
||||||
|
for(field in _superFields) {
|
||||||
|
if(!field.kind.match(FMethod(_))) // only catch methods
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var nfield = @:privateAccess TypeTools.toField(field);
|
||||||
|
switch ([field.kind, field.type]) {
|
||||||
|
case [FMethod(kind), TFun(args, ret)]:
|
||||||
|
if(kind == MethInline)
|
||||||
|
nfield.access.push(AInline);
|
||||||
|
if(kind == MethDynamic)
|
||||||
|
nfield.access.push(ADynamic);
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(nfield.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (fun.params != null && fun.params.length > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fun.ret = Utils.fixStdTypes(fun.ret);
|
||||||
|
|
||||||
|
var metas = nfield.meta;
|
||||||
|
var defaultValues:Map<String, Dynamic> = [];
|
||||||
|
var defaultEntry = null;
|
||||||
|
var isGeneric = false;
|
||||||
|
for(m in metas) {
|
||||||
|
if(m.name == ":value") {
|
||||||
|
defaultEntry = m;
|
||||||
|
switch(m.params[0].expr) {
|
||||||
|
case EObjectDecl(fields):
|
||||||
|
for(fil in fields)
|
||||||
|
defaultValues[fil.field] = fil.expr;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m.name == ":generic")
|
||||||
|
isGeneric = true;
|
||||||
|
}
|
||||||
|
if(isGeneric) continue;
|
||||||
|
|
||||||
|
if(defaultEntry != null)
|
||||||
|
metas.remove(defaultEntry);
|
||||||
|
|
||||||
|
for(arg in fun.args) {
|
||||||
|
var opt = false;
|
||||||
|
if(defaultValues.exists(arg.name)) {
|
||||||
|
arg.value = defaultValues[arg.name];
|
||||||
|
arg.opt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg.type = Utils.fixStdTypes(arg.type);
|
||||||
|
|
||||||
|
if(arg.opt) {
|
||||||
|
if(arg.type.getParameters()[0].name != "Null")
|
||||||
|
arg.type = TPath({name: "Null", params: [TPType(arg.type)], pack: []});//macro {Null<Dynamic>};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
superFields.push(nfield);
|
||||||
|
} catch(e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//superFields = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var shadowClass = macro class {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var definedFields:Array<String> = [];
|
||||||
|
|
||||||
|
//trace(getModuleName(cl));
|
||||||
|
|
||||||
|
var hasNew = false;
|
||||||
|
|
||||||
|
for(_field in [fields.copy(), superFields.copy()])
|
||||||
|
for(f in _field) {
|
||||||
|
if (f == null)
|
||||||
|
continue;
|
||||||
|
if (f.name == "new") {
|
||||||
|
hasNew = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (f.name.startsWith(FUNC_PREFIX))
|
||||||
|
continue;
|
||||||
|
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern) || f.access.contains(AInline))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(f.name == "hget" || f.name == "hset") continue; // sorry, no overwriting the hget and hset in custom classes, yet
|
||||||
|
if(definedFields.contains(f.name)) continue; // no duplicate fields
|
||||||
|
|
||||||
|
for(m in f.meta)
|
||||||
|
if (unallowedMetas.contains(m.name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(f.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (fun == null)
|
||||||
|
continue;
|
||||||
|
if (fun.params != null && fun.params.length > 0) // TODO: Support for this maybe?
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(fun.params == null)
|
||||||
|
fun.params = [];
|
||||||
|
|
||||||
|
var overrideExpr:Expr;
|
||||||
|
var returns:Bool = !fun.ret.match(TPath({name: "Void"}));
|
||||||
|
|
||||||
|
var name = f.name;
|
||||||
|
|
||||||
|
var arguments = fun.args == null ? [] : [for(a in fun.args) macro $i{a.name}];
|
||||||
|
|
||||||
|
if (returns) {
|
||||||
|
overrideExpr = macro {
|
||||||
|
var name:String = $v{name};
|
||||||
|
|
||||||
|
if (__interp != null) {
|
||||||
|
var v:Dynamic = null;
|
||||||
|
if (__interp.variables.exists(name) && Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||||
|
return v($a{arguments});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.$name($a{arguments});
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
overrideExpr = macro {
|
||||||
|
var name:String = $v{name};
|
||||||
|
|
||||||
|
if (__interp != null) {
|
||||||
|
var v:Dynamic = null;
|
||||||
|
if (__interp != null && __interp.variables.exists(name) && Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||||
|
v($a{arguments});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.$name($a{arguments});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var superFuncExpr:Expr = returns ? {
|
||||||
|
macro return super.$name($a{arguments});
|
||||||
|
} : {
|
||||||
|
macro super.$name($a{arguments});
|
||||||
|
};
|
||||||
|
|
||||||
|
var func:Function = {
|
||||||
|
ret: fun.ret,
|
||||||
|
params: fun.params.copy(),
|
||||||
|
expr: overrideExpr,
|
||||||
|
args: fun.args.copy()
|
||||||
|
};
|
||||||
|
|
||||||
|
var overrideField:Field = {
|
||||||
|
name: f.name,
|
||||||
|
access: f.access.copy(),
|
||||||
|
kind: FFun(func),
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
doc: f.doc,
|
||||||
|
meta: f.meta.copy()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!overrideField.access.contains(AOverride))
|
||||||
|
overrideField.access.push(AOverride);
|
||||||
|
|
||||||
|
var superField:Field = {
|
||||||
|
name: '$FUNC_PREFIX${f.name}',
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
kind: FFun({
|
||||||
|
ret: fun.ret,
|
||||||
|
params: fun.params.copy(),
|
||||||
|
expr: superFuncExpr,
|
||||||
|
args: fun.args.copy()
|
||||||
|
}),
|
||||||
|
access: f.access.copy()
|
||||||
|
};
|
||||||
|
if (superField.access.contains(AOverride))
|
||||||
|
superField.access.remove(AOverride);
|
||||||
|
shadowClass.fields.push(overrideField);
|
||||||
|
shadowClass.fields.push(superField);
|
||||||
|
definedFields.push(f.name);
|
||||||
|
default:
|
||||||
|
// fuck off >:(
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalFields = definedFields.length;
|
||||||
|
|
||||||
|
if(totalFields == 0 && !hasNew) {
|
||||||
|
//Sys.println(cl.pack.join(".") + "." + cl.name + ", " + totalFields);
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowClass.kind = TDClass({
|
||||||
|
pack: cl.pack.copy(),
|
||||||
|
name: cl.name
|
||||||
|
}, [
|
||||||
|
{name: "IHScriptCustomBehaviour", pack: ["hscript"]}
|
||||||
|
], false, true, false);
|
||||||
|
shadowClass.name = '${cl.name}$CLASS_SUFFIX';
|
||||||
|
var imports = Context.getLocalImports().copy();
|
||||||
|
Utils.setupMetas(shadowClass, imports);
|
||||||
|
|
||||||
|
// Adding hscript getters and setters
|
||||||
|
|
||||||
|
shadowClass.fields.push({
|
||||||
|
name: "__interp",
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
kind: FVar(TPath({
|
||||||
|
pack: ['hscript'],
|
||||||
|
name: 'Interp'
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
|
||||||
|
// Todo: make it possible to override
|
||||||
|
if(cl.name == "FunkinShader" || cl.name == "CustomShader" || cl.name == "MultiThreadedScript") {
|
||||||
|
Context.defineModule(cl.module, [shadowClass], imports);
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasHgetInSuper = false;
|
||||||
|
var hasHsetInSuper = false;
|
||||||
|
|
||||||
|
if(cl.name == "CustomShader") {
|
||||||
|
hasHgetInSuper = hasHsetInSuper = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: somehow check the super super class
|
||||||
|
for(_field in [fields.copy(), superFields.copy()])
|
||||||
|
for(f in _field) {
|
||||||
|
if (f.name == "new")
|
||||||
|
continue;
|
||||||
|
if (f.name.startsWith(FUNC_PREFIX))
|
||||||
|
continue;
|
||||||
|
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(f.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (fun.params != null && fun.params.length > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!hasHgetInSuper)
|
||||||
|
hasHgetInSuper = f.name == "hget";
|
||||||
|
if(!hasHsetInSuper)
|
||||||
|
hasHsetInSuper = f.name == "hset";
|
||||||
|
|
||||||
|
if(hasHgetInSuper && hasHsetInSuper)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hgetField = if(hasHgetInSuper) {
|
||||||
|
macro {
|
||||||
|
if(this.__interp.variables.exists("get_" + name))
|
||||||
|
return this.__interp.variables.get("get_" + name)();
|
||||||
|
if (this.__interp.variables.exists(name))
|
||||||
|
return this.__interp.variables.get(name);
|
||||||
|
return super.hget(name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
macro {
|
||||||
|
if(this.__interp.variables.exists("get_" + name))
|
||||||
|
return this.__interp.variables.get("get_" + name)();
|
||||||
|
if (this.__interp.variables.exists(name))
|
||||||
|
return this.__interp.variables.get(name);
|
||||||
|
return Reflect.getProperty(this, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hsetField = if(hasHsetInSuper) {
|
||||||
|
macro {
|
||||||
|
if(this.__interp.variables.exists("set_" + name)) {
|
||||||
|
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||||
|
}
|
||||||
|
if (this.__interp.variables.exists(name)) {
|
||||||
|
this.__interp.variables.set(name, val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return super.hset(name, val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
macro {
|
||||||
|
if(this.__interp.variables.exists("set_" + name)) {
|
||||||
|
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||||
|
}
|
||||||
|
if (this.__interp.variables.exists(name)) {
|
||||||
|
this.__interp.variables.set(name, val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
Reflect.setProperty(this, name, val);
|
||||||
|
return Reflect.field(this, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(hasHsetInSuper || hasHgetInSuper) return fields;
|
||||||
|
|
||||||
|
//trace(cl.name);
|
||||||
|
|
||||||
|
shadowClass.fields.push({
|
||||||
|
name: "hset",
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
access: hasHsetInSuper ? [AOverride, APublic] : [APublic],
|
||||||
|
kind: FFun({
|
||||||
|
ret: TPath({name: 'Dynamic', pack: []}),
|
||||||
|
params: [],
|
||||||
|
expr: hsetField,
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "name",
|
||||||
|
opt: false,
|
||||||
|
meta: [],
|
||||||
|
type: TPath({name: "String", pack: []})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "val",
|
||||||
|
opt: false,
|
||||||
|
meta: [],
|
||||||
|
type: TPath({name: "Dynamic", pack: []})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
shadowClass.fields.push({
|
||||||
|
name: "hget",
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
access: hasHgetInSuper ? [AOverride, APublic] : [APublic],
|
||||||
|
kind: FFun({
|
||||||
|
ret: TPath({name: 'Dynamic', pack: []}),
|
||||||
|
params: [],
|
||||||
|
expr: hgetField,
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "name",
|
||||||
|
opt: false,
|
||||||
|
meta: [],
|
||||||
|
type: TPath({name: "String", pack: []})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
/*var p = new Printer();
|
||||||
|
var aa = p.printTypeDefinition(shadowClass);
|
||||||
|
if(aa.length < 5024)
|
||||||
|
trace(aa);
|
||||||
|
if(aa.indexOf("pack") >= 0)
|
||||||
|
if(cl.name == "FunkinShader")*/
|
||||||
|
|
||||||
|
Context.defineModule(cl.module, [shadowClass], imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
class ClassExtendMacro {
|
||||||
|
public var usedClass:Class<Dynamic>;
|
||||||
|
public var className:String;
|
||||||
|
}
|
||||||
|
#end
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
package hscript.macros;
|
||||||
|
|
||||||
|
#if macro
|
||||||
|
import Type.ValueType;
|
||||||
|
import haxe.macro.ComplexTypeTools;
|
||||||
|
import haxe.macro.Expr;
|
||||||
|
import haxe.macro.Context;
|
||||||
|
import haxe.macro.Printer;
|
||||||
|
import haxe.macro.Compiler;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class UsingHandler {
|
||||||
|
public static function init() {
|
||||||
|
#if !display
|
||||||
|
if(Context.defined("display")) return;
|
||||||
|
for(apply in Config.ALLOWED_ABSTRACT_AND_ENUM) {
|
||||||
|
Compiler.addGlobalMetadata(apply, '@:build(hscript.macros.UsingHandler.build())');
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function build():Array<Field> {
|
||||||
|
var fields = Context.getBuildFields();
|
||||||
|
var clRef = Context.getLocalClass();
|
||||||
|
if (clRef == null) return fields;
|
||||||
|
var cl = clRef.get();
|
||||||
|
|
||||||
|
if (/* cl.name.startsWith("Flx") && */ cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType") && !cl.name.contains("_HSC")) {
|
||||||
|
var metas = cl.meta.get();
|
||||||
|
|
||||||
|
var trimEnum = cl.name.substr(0, cl.name.length - 6);
|
||||||
|
|
||||||
|
var key = cl.module;
|
||||||
|
var fkey = cl.module + "." + trimEnum;
|
||||||
|
if(key == "lime.system.Locale") return fields; // Error: Unknown identifier : currentLocale, Due to Func
|
||||||
|
if(key == "cpp.Function") return fields; // Error: Unknown identifier : nativeGetProcAddress, Due to Func
|
||||||
|
if(key == "haxe.ds.Vector") return fields; // Error: haxe.ds._Vector.VectorData<blit.T> has no field blit, Due to Func
|
||||||
|
if(key == "haxe.display.Display") return fields; // Error: haxe.display.DisplayItemKind<haxe.display.DisplayLiteral<Dynamic>> has no field Null, Due to Func
|
||||||
|
if(key == "cpp.Callable") return fields; // Error: cpp.Function.fromStaticFunction must be called on static function, Due to Func
|
||||||
|
if(key == "haxe.display.JsonAnonStatusKind") return fields; // Error: cannot initialize a variable of type 'char *' with an rvalue of type 'const char *', Due to Func
|
||||||
|
if(key == "cpp.CharStar") return fields; // Error: cannot initialize a variable of type 'char *' with an rvalue of type 'const char *', Due to Func
|
||||||
|
if(Config.DISALLOW_ABSTRACT_AND_ENUM.contains(cl.module) || Config.DISALLOW_ABSTRACT_AND_ENUM.contains(fkey)) return fields;
|
||||||
|
if(cl.module.contains("_")) return fields; // Weird issue, sorry
|
||||||
|
|
||||||
|
var shadowClass = macro class {
|
||||||
|
|
||||||
|
};
|
||||||
|
shadowClass.kind = TDClass();
|
||||||
|
shadowClass.params = switch(cl.params.length) {
|
||||||
|
case 0:
|
||||||
|
null;
|
||||||
|
case 1:
|
||||||
|
[{
|
||||||
|
name: "T",
|
||||||
|
}];
|
||||||
|
default:
|
||||||
|
[for(k=>e in cl.params) {
|
||||||
|
name: "T" + Std.int(k+1)
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
shadowClass.name = '${cl.name.substr(0, cl.name.length - 6)}_HSC';
|
||||||
|
|
||||||
|
var imports = Context.getLocalImports().copy();
|
||||||
|
Utils.setupMetas(shadowClass, imports);
|
||||||
|
//trace(cl.module);
|
||||||
|
|
||||||
|
for(f in fields)
|
||||||
|
switch(f.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (f.access.contains(AStatic)) {
|
||||||
|
if (fun.expr != null) {
|
||||||
|
fun.expr = macro @:privateAccess $e{fun.expr};
|
||||||
|
shadowClass.fields.push(f);
|
||||||
|
|
||||||
|
/*var trimEnum = cl.name.substr(0, cl.name.length - 6);
|
||||||
|
|
||||||
|
var returns:Bool = !fun.ret.match(TPath({name: "Void"}));
|
||||||
|
|
||||||
|
var name = f.name;
|
||||||
|
|
||||||
|
var arguments = fun.args == null ? [] : [for(a in fun.args) macro $i{a.name}];
|
||||||
|
|
||||||
|
var expr:Expr = Context.parse('${returns?"return " : ""} $trimEnum.$name(${[for(a in fun.args) a.name].join(", ")})', f.pos);
|
||||||
|
|
||||||
|
var func:Function = {
|
||||||
|
ret: fun.ret,
|
||||||
|
params: fun.params.copy(),
|
||||||
|
expr: expr,
|
||||||
|
args: fun.args.copy()
|
||||||
|
};
|
||||||
|
|
||||||
|
var field:Field = {
|
||||||
|
pos: f.pos,
|
||||||
|
name: f.name,
|
||||||
|
meta: f.meta,
|
||||||
|
kind: FFun(func),
|
||||||
|
doc: null,//f.doc,
|
||||||
|
access: [APublic, AStatic]
|
||||||
|
}
|
||||||
|
shadowClass.fields.push(field);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case FProp(get, set, t, e):
|
||||||
|
if (get == "default" && (set == "never" || set == "null")) {
|
||||||
|
shadowClass.fields.push(f);
|
||||||
|
}
|
||||||
|
case FVar(t, e):
|
||||||
|
if (f.access.contains(AStatic) || cl.meta.has(":enum") || f.name.toUpperCase() == f.name) {
|
||||||
|
var name:String = f.name;
|
||||||
|
var enumType:String = cl.name;
|
||||||
|
var pack = cl.module.split(".");
|
||||||
|
|
||||||
|
//trace(pack, cl.name, name, cl.module);
|
||||||
|
|
||||||
|
if(pack[pack.length - 1] == trimEnum)
|
||||||
|
pack.pop();
|
||||||
|
|
||||||
|
var complexType:ComplexType = t;
|
||||||
|
if(complexType == null && e != null) {
|
||||||
|
complexType = switch(e.expr) {
|
||||||
|
case EConst(CRegexp(_)): TPath({ name: "EReg", pack: [] });
|
||||||
|
|
||||||
|
default: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(complexType == null) {
|
||||||
|
complexType = TPath({
|
||||||
|
name: trimEnum,
|
||||||
|
pack: [],//pack
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = Context.parse('@:privateAccess ($trimEnum.$name)', f.pos); // '${pack.join(".")}.${trimEnum}.$name'
|
||||||
|
|
||||||
|
var field:Field = {
|
||||||
|
pos: f.pos,
|
||||||
|
name: f.name,
|
||||||
|
meta: f.meta,
|
||||||
|
kind: FVar(null, code),
|
||||||
|
doc: f.doc,
|
||||||
|
access: [APublic, AStatic]
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowClass.fields.push(field);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
//var printer = new Printer();
|
||||||
|
//for(field in shadowClass.fields)
|
||||||
|
// trace(printer.printField(field));
|
||||||
|
|
||||||
|
Context.defineModule(cl.module, [shadowClass], imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#end
|
||||||
@@ -1,107 +1,20 @@
|
|||||||
package hscript;
|
package hscript.macros;
|
||||||
|
|
||||||
import Type.ValueType;
|
|
||||||
import haxe.macro.ComplexTypeTools;
|
|
||||||
#if macro
|
#if macro
|
||||||
|
import haxe.macro.Type.ClassType;
|
||||||
|
import Type.ValueType;
|
||||||
|
import haxe.macro.Expr.Function;
|
||||||
import haxe.macro.Expr;
|
import haxe.macro.Expr;
|
||||||
import haxe.macro.Context;
|
import haxe.macro.Type.MetaAccess;
|
||||||
import haxe.macro.Printer;
|
import haxe.macro.Type.FieldKind;
|
||||||
import haxe.macro.Compiler;
|
import haxe.macro.Type.ClassField;
|
||||||
|
import haxe.macro.Type.VarAccess;
|
||||||
|
import haxe.macro.*;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
class UsingHandler {
|
class Utils {
|
||||||
public var usedClass:Class<Dynamic>;
|
public static function fixStdTypes(type:ComplexType) {
|
||||||
public var className:String;
|
|
||||||
|
|
||||||
public function new(className:String, usedClass:Class<Dynamic>) {
|
|
||||||
this.className = className;
|
|
||||||
this.usedClass = usedClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function init() {
|
|
||||||
Compiler.addGlobalMetadata('flixel', '@:build(hscript.UsingHandler.build())');
|
|
||||||
Compiler.addGlobalMetadata('openfl.display.BlendMode', '@:build(hscript.UsingHandler.build())');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function build():Array<Field> {
|
|
||||||
var fields = Context.getBuildFields();
|
|
||||||
var clRef = Context.getLocalClass();
|
|
||||||
if (clRef == null) return fields;
|
|
||||||
var cl = clRef.get();
|
|
||||||
|
|
||||||
if (/* cl.name.startsWith("Flx") && */ cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType")) {
|
|
||||||
var metas = cl.meta.get();
|
|
||||||
|
|
||||||
var shadowClass = macro class {
|
|
||||||
|
|
||||||
};
|
|
||||||
shadowClass.kind = TDClass();
|
|
||||||
shadowClass.params = switch(cl.params.length) {
|
|
||||||
case 0:
|
|
||||||
null;
|
|
||||||
case 1:
|
|
||||||
[
|
|
||||||
{
|
|
||||||
name: "T",
|
|
||||||
}
|
|
||||||
];
|
|
||||||
default:
|
|
||||||
[for(k=>e in cl.params) {
|
|
||||||
name: "T" + Std.int(k+1)
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
shadowClass.name = '${cl.name.substr(0, cl.name.length - 6)}_HSC';
|
|
||||||
|
|
||||||
var imports = Context.getLocalImports().copy();
|
|
||||||
setupMetas(shadowClass, imports);
|
|
||||||
|
|
||||||
for(f in fields)
|
|
||||||
switch(f.kind) {
|
|
||||||
case FFun(fun):
|
|
||||||
if (f.access.contains(AStatic)) {
|
|
||||||
if (fun.expr != null)
|
|
||||||
shadowClass.fields.push(f);
|
|
||||||
}
|
|
||||||
case FProp(get, set, t, e):
|
|
||||||
if (get == "default" && (set == "never" || set == "null"))
|
|
||||||
shadowClass.fields.push(f);
|
|
||||||
case FVar(t, e):
|
|
||||||
if (f.access.contains(AStatic) || cl.meta.has(":enum") || f.name.toUpperCase() == f.name) {
|
|
||||||
var name:String = f.name;
|
|
||||||
var enumType:String = cl.name;
|
|
||||||
var pack = cl.module.split(".");
|
|
||||||
pack.pop();
|
|
||||||
var complexType:ComplexType = t != null ? t : (name.contains("REGEX") ? TPath({
|
|
||||||
name: "EReg",
|
|
||||||
pack: []
|
|
||||||
}) : TPath({
|
|
||||||
name: cl.name.substr(0, cl.name.length - 6),
|
|
||||||
pack: pack}));
|
|
||||||
var field:Field = {
|
|
||||||
pos: f.pos,
|
|
||||||
name: f.name,
|
|
||||||
meta: f.meta,
|
|
||||||
kind: FVar(complexType, {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: ECast(e, complexType)
|
|
||||||
}),
|
|
||||||
doc: f.doc,
|
|
||||||
access: [APublic, AStatic]
|
|
||||||
}
|
|
||||||
|
|
||||||
shadowClass.fields.push(field);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
Context.defineModule(cl.module + "_HSC", [shadowClass], imports);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function fixStdTypes(type:ComplexType) {
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case TPath({name: "StdTypes"}):
|
case TPath({name: "StdTypes"}):
|
||||||
var a:TypePath = type.getParameters()[0];
|
var a:TypePath = type.getParameters()[0];
|
||||||
@@ -113,16 +26,9 @@ class UsingHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function setupMetas(shadowClass:TypeDefinition, imports) {
|
public static function setupMetas(shadowClass:TypeDefinition, imports) {
|
||||||
shadowClass.meta = [{
|
shadowClass.meta = [];
|
||||||
name: ':dox',
|
shadowClass.meta.push({name: ":dox", params: [macro hide], pos: Context.currentPos()});
|
||||||
pos: Context.currentPos(),
|
shadowClass.meta.push({name: ":noCompletion", params: [], pos: Context.currentPos()});
|
||||||
params: [
|
|
||||||
{
|
|
||||||
expr: EConst(CIdent("hide")),
|
|
||||||
pos: Context.currentPos()
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}];
|
|
||||||
var module = Context.getModule(Context.getLocalModule());
|
var module = Context.getModule(Context.getLocalModule());
|
||||||
for(t in module) {
|
for(t in module) {
|
||||||
switch(t) {
|
switch(t) {
|
||||||
@@ -300,9 +206,4 @@ class UsingHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
class UsingHandler {
|
|
||||||
public var usedClass:Class<Dynamic>;
|
|
||||||
public var className:String;
|
|
||||||
}
|
|
||||||
#end
|
#end
|
||||||
Reference in New Issue
Block a user