Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f2dec1634 | ||
|
|
51188173bb | ||
|
|
d0797ad5d8 | ||
|
|
9b37bd532e | ||
|
|
333352edcf | ||
|
|
05783773af | ||
|
|
59ee20ee7a | ||
|
|
87f2c1b062 | ||
|
|
b85cefea56 | ||
|
|
2e28f863f3 | ||
|
|
ddaa4d1741 | ||
|
|
732bd1520a | ||
|
|
1d67946f3f | ||
|
|
fab6d7e662 | ||
|
|
6e20578a81 | ||
|
|
dc5282c32e | ||
|
|
812abae6e5 | ||
|
|
b3b512d027 | ||
|
|
ed296c4c7f | ||
|
|
595bb47249 | ||
|
|
daad1a4fa8 | ||
|
|
daef1ac198 | ||
|
|
3b9d88b252 | ||
|
|
809f8229b4 | ||
|
|
ffb1ee2523 | ||
|
|
0903718314 | ||
|
|
e0cb883ae4 | ||
|
|
17449dd9d5 | ||
|
|
7963631a1d | ||
|
|
77d88f4b34 | ||
|
|
c5e3ab1162 | ||
|
|
75041c1db9 | ||
|
|
558a4c0782 | ||
|
|
995c3b9c8e | ||
|
|
0a64bca9ce | ||
|
|
b7b12b6cbb | ||
|
|
5684ca8671 | ||
|
|
3c81360dc2 | ||
|
|
fc50ebdf90 | ||
|
|
4d6e8db5ff | ||
|
|
938ffac57e | ||
|
|
50aaffb101 | ||
|
|
4f9b449c6e | ||
|
|
c1a36a3f4b | ||
|
|
4ca6e2a680 | ||
|
|
11db805c34 | ||
|
|
f1f700ab69 | ||
|
|
9eeb8ddb80 | ||
|
|
95de26a6d0 | ||
|
|
88c2e28dbc | ||
|
|
30b7a9e4d4 | ||
|
|
37542065d6 | ||
|
|
c9608f7760 | ||
|
|
6ba54b0e77 | ||
|
|
f9bb3105c8 | ||
|
|
4b5baa9b5f | ||
|
|
6dedd87260 | ||
|
|
91317222fb | ||
|
|
494953a8cc | ||
|
|
ae4d8be50c | ||
|
|
d34790e05c | ||
|
|
b77e15c6d6 | ||
|
|
54195d5811 | ||
|
|
9c7907f91a | ||
|
|
0601b8def6 | ||
|
|
841261f199 | ||
|
|
7124b6c4ce | ||
|
|
ad7beec559 | ||
|
|
bd4fc51392 | ||
|
|
54d994a879 | ||
|
|
891a085f2b | ||
|
|
e7ccd2e72d | ||
|
|
459a39e65d | ||
|
|
36eb0fca8b | ||
|
|
53b9e22f26 | ||
|
|
8ff3f5e351 | ||
|
|
e6a2c443cb | ||
|
|
4f25ab162d | ||
|
|
0520d9f187 | ||
|
|
cc3c21b7e3 | ||
|
|
ae9560124e | ||
|
|
085f4ec37e | ||
|
|
476c3a9cc9 | ||
|
|
1bc5ac8768 | ||
|
|
4bdff11b87 |
@@ -7,7 +7,7 @@ import hscript.Printer;
|
||||
import hscript.Checker;
|
||||
import haxe.unit.*;
|
||||
|
||||
class Test extends TestCase {
|
||||
class TestHScript extends TestCase {
|
||||
function assertScript(x,v:Dynamic,?vars : Dynamic, allowTypes=false, ?pos:haxe.PosInfos) {
|
||||
var p = new hscript.Parser();
|
||||
p.allowTypes = allowTypes;
|
||||
@@ -101,6 +101,7 @@ class Test extends TestCase {
|
||||
assertScript("/**/0", 0);
|
||||
assertScript("x=1;x*=-2", -2);
|
||||
assertScript("var f = x -> x + 1; f(3)", 4);
|
||||
assertScript("var f = () -> 55; f()", 55);
|
||||
assertScript("var f = (x) -> x + 1; f(3)", 4);
|
||||
assertScript("var f = (x:Int) -> x + 1; f(3)", 4);
|
||||
assertScript("var f = (x,y) -> x + y; f(3,1)", 4);
|
||||
@@ -110,6 +111,8 @@ class Test extends TestCase {
|
||||
assertScript("var f:(x:Int, y:Int)->Int = (x:Int,y:Int) -> x + y; f(3,1)", 4, null, true);
|
||||
assertScript("var f:(x:Int)->(y:Int, z:Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2)", 6, null, true);
|
||||
assertScript("var f:(x:Int)->(Int, Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2)", 6, null, true);
|
||||
assertScript("var a = 10; var b = 5; a - -b", 15);
|
||||
assertScript("var a = 10; var b = 5; a - b / 2", 7.5);
|
||||
}
|
||||
|
||||
function testMap():Void {
|
||||
@@ -170,7 +173,7 @@ class Test extends TestCase {
|
||||
#end
|
||||
|
||||
var runner = new TestRunner();
|
||||
runner.add(new Test());
|
||||
runner.add(new TestHScript());
|
||||
var succeed = runner.run();
|
||||
|
||||
#if sys
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
-main Test
|
||||
-main TestHScript
|
||||
-dce no
|
||||
-lib hx3compat
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "hscript",
|
||||
"url": "https://github.com/HaxeFoundation/hscript",
|
||||
"license": "MIT",
|
||||
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
|
||||
"version": "2.4.0",
|
||||
"releasenote": "Haxe 4.0 final + type checking/completion (hscript.Checker)",
|
||||
"contributors": ["ncannasse"]
|
||||
}
|
||||
{
|
||||
"name": "hscript",
|
||||
"url": "https://github.com/HaxeFoundation/hscript",
|
||||
"license": "MIT",
|
||||
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
|
||||
"version": "2.4.0",
|
||||
"releasenote": "Haxe 4.0 final + type checking/completion (hscript.Checker)",
|
||||
"contributors": ["ncannasse","HaxeFoundation"]
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project version="2">
|
||||
<!-- Output SWF options -->
|
||||
<output>
|
||||
<movie outputType="Application" />
|
||||
<movie input="" />
|
||||
<movie path="hscript.swf" />
|
||||
<movie fps="30" />
|
||||
<movie width="800" />
|
||||
<movie height="600" />
|
||||
<movie version="9" />
|
||||
<movie minorVersion="0" />
|
||||
<movie platform="Flash Player" />
|
||||
<movie background="#FFFFFF" />
|
||||
</output>
|
||||
<!-- Other classes to be compiled into your SWF -->
|
||||
<classpaths>
|
||||
<!-- example: <class path="..." /> -->
|
||||
</classpaths>
|
||||
<!-- Build options -->
|
||||
<build>
|
||||
<option directives="" />
|
||||
<option flashStrict="True" />
|
||||
<option noInlineOnDebug="False" />
|
||||
<option mainClass="Test" />
|
||||
<option enabledebug="False" />
|
||||
<option additional="-dce no" />
|
||||
</build>
|
||||
<!-- haxelib libraries -->
|
||||
<haxelib>
|
||||
<!-- example: <library name="..." /> -->
|
||||
</haxelib>
|
||||
<!-- Class files to compile (other referenced classes will automatically be included) -->
|
||||
<compileTargets>
|
||||
<!-- example: <compile path="..." /> -->
|
||||
</compileTargets>
|
||||
<!-- Assets to embed into the output SWF -->
|
||||
<library>
|
||||
<!-- example: <asset path="..." id="..." update="..." glyphs="..." mode="..." place="..." sharepoint="..." /> -->
|
||||
</library>
|
||||
<!-- Paths to exclude from the Project Explorer tree -->
|
||||
<hiddenPaths>
|
||||
<hidden path="haxelib.xml" />
|
||||
<hidden path="hscript.hxml" />
|
||||
<hidden path="hscript.js" />
|
||||
<hidden path="hscript.n" />
|
||||
<hidden path="hscript.swf" />
|
||||
<hidden path="hscript9.swf" />
|
||||
<hidden path="release.bat" />
|
||||
<hidden path="release.zip" />
|
||||
<hidden path="obj" />
|
||||
</hiddenPaths>
|
||||
<!-- Executed before build -->
|
||||
<preBuildCommand />
|
||||
<!-- Executed after build -->
|
||||
<postBuildCommand alwaysRun="False" />
|
||||
<!-- Other project options -->
|
||||
<options>
|
||||
<option showHiddenPaths="False" />
|
||||
<option testMovie="Default" />
|
||||
<option testMovieCommand="" />
|
||||
</options>
|
||||
<!-- Plugin storage -->
|
||||
<storage />
|
||||
</project>
|
||||
+8
-1
@@ -36,6 +36,7 @@ class Async {
|
||||
var currentLoop : Expr;
|
||||
var currentBreak : Expr -> Expr;
|
||||
var uid = 0;
|
||||
public var asyncIdents : Map<String,Bool>;
|
||||
|
||||
static var nullExpr : Expr = #if hscriptPos { e : null, pmin : 0, pmax : 0, origin : "<null>", line : 0 } #else null #end;
|
||||
static var nullId = mk(EIdent("null"), nullExpr);
|
||||
@@ -207,11 +208,17 @@ class Async {
|
||||
return syncFlag;
|
||||
}
|
||||
|
||||
inline function isAsyncIdent( id : String ) {
|
||||
return asyncIdents == null || asyncIdents.exists(id);
|
||||
}
|
||||
|
||||
function checkSync( e : Expr ) {
|
||||
if( !syncFlag )
|
||||
return;
|
||||
switch( expr(e) ) {
|
||||
case ECall(_):
|
||||
case ECall(expr(_) => EIdent(i),_) if( isAsyncIdent(i) || vars.get(i) == Defined ):
|
||||
syncFlag = false;
|
||||
case ECall(expr(_) => EField(_,i),_) if( isAsyncIdent(i) ):
|
||||
syncFlag = false;
|
||||
case EFunction(_,_,name,_) if( name != null ):
|
||||
syncFlag = false;
|
||||
|
||||
@@ -140,6 +140,10 @@ class Bytes {
|
||||
#end
|
||||
bout.addByte(Type.enumIndex(e));
|
||||
switch( e ) {
|
||||
case EImport(c):
|
||||
// TODO
|
||||
case EClass(_, _, _, _):
|
||||
// TODO
|
||||
case EConst(c):
|
||||
doEncodeConst(c);
|
||||
case EIdent(v):
|
||||
|
||||
+74
-17
@@ -48,6 +48,8 @@ typedef CNamedType = {
|
||||
typedef CClass = {> CNamedType,
|
||||
@:optional var superClass : TType;
|
||||
@:optional var constructor : CField;
|
||||
@:optional var interfaces : Array<TType>;
|
||||
@:optional var isInterface : Bool;
|
||||
var fields : Map<String,CField>;
|
||||
var statics : Map<String,CField>;
|
||||
}
|
||||
@@ -121,12 +123,19 @@ class CheckerTypes {
|
||||
fields : new Map(),
|
||||
statics : new Map(),
|
||||
};
|
||||
if( c.isInterface )
|
||||
cl.isInterface = true;
|
||||
for( p in c.params )
|
||||
cl.params.push(TParam(p));
|
||||
todo.push(function() {
|
||||
localParams = [for( t in cl.params ) c.path+"."+Checker.typeStr(t) => t];
|
||||
if( c.superClass != null )
|
||||
cl.superClass = getType(c.superClass.path, [for( t in c.superClass.params ) makeXmlType(t)]);
|
||||
if( c.interfaces != null ) {
|
||||
cl.interfaces = [];
|
||||
for( i in c.interfaces )
|
||||
cl.interfaces.push(getType(i.path, [for( t in i.params ) makeXmlType(t)]));
|
||||
}
|
||||
var pkeys = [];
|
||||
for( f in c.fields ) {
|
||||
if( f.isOverride || f.name.substr(0,4) == "get_" || f.name.substr(0,4) == "set_" ) continue;
|
||||
@@ -295,9 +304,17 @@ class Checker {
|
||||
}
|
||||
|
||||
public function setGlobals( cl : CClass ) {
|
||||
for( f in cl.fields )
|
||||
if( f.isPublic )
|
||||
setGlobal(f.name, f.params.length == 0 ? f.t : TLazy(function() return apply(f.t,f.params,[for( i in 0...f.params.length) makeMono()])));
|
||||
while( true ) {
|
||||
for( f in cl.fields )
|
||||
if( f.isPublic )
|
||||
setGlobal(f.name, f.params.length == 0 ? f.t : TLazy(function() return apply(f.t,f.params,[for( i in 0...f.params.length) makeMono()])));
|
||||
if( cl.superClass == null )
|
||||
break;
|
||||
cl = switch( cl.superClass ) {
|
||||
case TInst(c,_): c;
|
||||
default: throw "assert";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function removeGlobal( name : String ) {
|
||||
@@ -580,6 +597,8 @@ class Checker {
|
||||
case [TDynamic, _]:
|
||||
return true;
|
||||
case [TAnon(a1),TAnon(a2)]:
|
||||
if( a2.length == 0 ) // always unify with {}
|
||||
return true;
|
||||
var m = new Map();
|
||||
for( f in a1 )
|
||||
m.set(f.name, f);
|
||||
@@ -595,6 +614,18 @@ class Checker {
|
||||
return true;
|
||||
case [TInst(cl1,pl1), TInst(cl2,pl2)]:
|
||||
while( cl1 != cl2 ) {
|
||||
if( cl1.interfaces != null ) {
|
||||
for( i in cl1.interfaces ) {
|
||||
switch( i ) {
|
||||
case TInst(cli, args):
|
||||
var i = TInst(cli, [for( a in args ) apply(a, cl1.params, pl1)]);
|
||||
if( tryUnify(i, t2) )
|
||||
return true;
|
||||
default:
|
||||
throw "assert";
|
||||
}
|
||||
}
|
||||
}
|
||||
switch( cl1.superClass ) {
|
||||
case null: return false;
|
||||
case TInst(c, args):
|
||||
@@ -693,23 +724,42 @@ class Checker {
|
||||
}
|
||||
}
|
||||
|
||||
public function getFields( t : TType ) {
|
||||
public function getFields( t : TType ) : Array<{ name : String, t : TType }> {
|
||||
var fields = [];
|
||||
while( t != null ) {
|
||||
t = follow(t);
|
||||
switch( t ) {
|
||||
case TInst(c, args):
|
||||
switch( follow(t) ) {
|
||||
case TInst(c, args):
|
||||
var map = (t) -> apply(t,c.params,args);
|
||||
while( c != null ) {
|
||||
for( fname in c.fields.keys() ) {
|
||||
var f = c.fields.get(fname);
|
||||
fields.push({ name : f.name, t : f.t });
|
||||
if( !f.isPublic || !f.complete ) continue;
|
||||
var name = f.name, t = map(f.t);
|
||||
if( allowAsync && StringTools.startsWith(name,"a_") ) {
|
||||
t = unasync(t);
|
||||
name = name.substr(2);
|
||||
}
|
||||
fields.push({ name : name, t : t });
|
||||
}
|
||||
if( c.isInterface && c.interfaces != null ) {
|
||||
for( i in c.interfaces ) {
|
||||
for( f in getFields(i) )
|
||||
fields.push({ name : f.name, t : map(f.t) });
|
||||
}
|
||||
}
|
||||
if( c.superClass == null ) break;
|
||||
switch( c.superClass ) {
|
||||
case TInst(csup,args):
|
||||
var curMap = map;
|
||||
map = (t) -> curMap(apply(t,csup.params,args));
|
||||
c = csup;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
t = c.superClass;
|
||||
case TAnon(fl):
|
||||
for( f in fl )
|
||||
fields.push({ name : f.name, t : f.t });
|
||||
break;
|
||||
default:
|
||||
}
|
||||
case TAnon(fl):
|
||||
for( f in fl )
|
||||
fields.push({ name : f.name, t : f.t });
|
||||
default:
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
@@ -726,6 +776,13 @@ class Checker {
|
||||
if( cf.t == null ) cf = null;
|
||||
}
|
||||
}
|
||||
if( cf == null && c.isInterface && c.interfaces != null ) {
|
||||
for( i in c.interfaces ) {
|
||||
var ft = getField(i, f, e, forWrite);
|
||||
if( ft != null )
|
||||
return apply(ft, c.params, args);
|
||||
}
|
||||
}
|
||||
if( cf == null ) {
|
||||
if( c.superClass == null ) return null;
|
||||
var ft = getField(c.superClass, f, e, forWrite);
|
||||
@@ -917,7 +974,7 @@ class Checker {
|
||||
return TVoid;
|
||||
case EObject(fl):
|
||||
switch( withType ) {
|
||||
case WithType(follow(_) => TAnon(tfields)):
|
||||
case WithType(follow(_) => TAnon(tfields)) if( tfields.length > 0 ):
|
||||
var map = [for( f in tfields ) f.name => f];
|
||||
return TAnon([for( f in fl ) {
|
||||
var ft = map.get(f.name);
|
||||
@@ -930,7 +987,7 @@ class Checker {
|
||||
default:
|
||||
return TAnon([for( f in fl ) { t : typeExpr(f.e, Value), opt : false, name : f.name }]);
|
||||
}
|
||||
case EBreak, EContinue:
|
||||
case EBreak, EContinue, EImport(_):
|
||||
return TVoid;
|
||||
case EReturn(v):
|
||||
var et = v == null ? TVoid : typeExpr(v, allowReturn == null ? Value : WithType(allowReturn));
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package hscript;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class CustomClassHandler implements IHScriptCustomConstructor {
|
||||
public static var staticHandler = new StaticHandler();
|
||||
|
||||
public var ogInterp:Interp;
|
||||
public var name:String;
|
||||
public var fields:Array<Expr>;
|
||||
public var extend:String;
|
||||
public var interfaces:Array<String>;
|
||||
|
||||
public function new(ogInterp:Interp, name:String, fields:Array<Expr>, ?extend:String, ?interfaces:Array<String>) {
|
||||
this.ogInterp = ogInterp;
|
||||
this.name = name;
|
||||
this.fields = fields;
|
||||
this.extend = extend;
|
||||
this.interfaces = interfaces;
|
||||
}
|
||||
|
||||
public function hnew(args:Array<Dynamic>):Dynamic {
|
||||
var interp = new Interp();
|
||||
|
||||
interp.errorHandler = ogInterp.errorHandler;
|
||||
|
||||
var cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
|
||||
var _class = Type.createInstance(cl, args);
|
||||
|
||||
var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
|
||||
var capturedLocals:Map<String, {r:Dynamic, depth:Int}> = [];
|
||||
for(k=>e in __capturedLocals)
|
||||
if (e != null && e.depth <= 0)
|
||||
capturedLocals.set(k, e);
|
||||
|
||||
var disallowCopy = Type.getInstanceFields(cl);
|
||||
|
||||
//trace("Locals");
|
||||
for (key => value in capturedLocals) {
|
||||
if(!disallowCopy.contains(key)) {
|
||||
interp.locals.set(key, {r: value, depth: -1});
|
||||
//trace(key, value);
|
||||
}
|
||||
}
|
||||
//trace("Variables");
|
||||
for (key => value in ogInterp.variables) {
|
||||
if(!disallowCopy.contains(key)) {
|
||||
interp.variables.set(key, value);
|
||||
//trace(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
for(expr in fields) {
|
||||
@:privateAccess
|
||||
interp.exprReturn(expr);
|
||||
}
|
||||
|
||||
interp.variables.set("super", staticHandler);
|
||||
|
||||
_class.__interp = interp;
|
||||
interp.scriptObject = _class;
|
||||
|
||||
var newFunc = interp.variables.get("new");
|
||||
if(newFunc != null) {
|
||||
Reflect.callMethod(null, newFunc, args);
|
||||
}
|
||||
|
||||
for(variable => value in interp.variables) {
|
||||
if(variable == "this") continue;
|
||||
}
|
||||
|
||||
return _class;
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
class TemplateClass implements IHScriptCustomBehaviour {
|
||||
public var __interp:Interp;
|
||||
|
||||
public function hset(name:String, val:Dynamic):Dynamic {
|
||||
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);
|
||||
}
|
||||
public function hget(name:String):Dynamic {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
class StaticHandler {
|
||||
public function new() {}
|
||||
}
|
||||
+10
-5
@@ -45,10 +45,10 @@ enum Expr {
|
||||
#end
|
||||
EConst( c : Const );
|
||||
EIdent( v : String );
|
||||
EVar( n : String, ?t : CType, ?e : Expr );
|
||||
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
|
||||
EParent( e : Expr );
|
||||
EBlock( e : Array<Expr> );
|
||||
EField( e : Expr, f : String );
|
||||
EField( e : Expr, f : String , ?safe : Bool );
|
||||
EBinop( op : String, e1 : Expr, e2 : Expr );
|
||||
EUnop( op : String, prefix : Bool, e : Expr );
|
||||
ECall( e : Expr, params : Array<Expr> );
|
||||
@@ -57,19 +57,22 @@ enum Expr {
|
||||
EFor( v : String, it : Expr, e : Expr );
|
||||
EBreak;
|
||||
EContinue;
|
||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType );
|
||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||
EReturn( ?e : Expr );
|
||||
EArray( e : Expr, index : Expr );
|
||||
EArrayDecl( e : Array<Expr> );
|
||||
EArrayDecl( e : Array<Expr>, ?wantedType: CType );
|
||||
ENew( cl : String, params : Array<Expr> );
|
||||
EThrow( e : Expr );
|
||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||
EObject( fl : Array<{ name : String, e : Expr }> );
|
||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr);
|
||||
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr );
|
||||
EDoWhile( cond : Expr, e : Expr);
|
||||
EMeta( name : String, args : Array<Expr>, e : Expr );
|
||||
ECheckType( e : Expr, t : CType );
|
||||
|
||||
EImport( c : String, ?asname:String );
|
||||
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||
}
|
||||
|
||||
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||
@@ -117,6 +120,8 @@ enum Error {
|
||||
EInvalidOp( op : String );
|
||||
EInvalidAccess( f : String );
|
||||
ECustom( msg : String );
|
||||
EInvalidClass( className : String);
|
||||
EAlreadyExistingClass( className : String);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package hscript;
|
||||
|
||||
interface IHScriptCustomBehaviour {
|
||||
public function hset(name:String, val:Dynamic):Dynamic;
|
||||
public function hget(name:String):Dynamic;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package hscript;
|
||||
|
||||
interface IHScriptCustomConstructor {
|
||||
public function hnew(args:Array<Dynamic>):Dynamic;
|
||||
}
|
||||
+793
-463
File diff suppressed because it is too large
Load Diff
@@ -79,6 +79,8 @@ class Macro {
|
||||
#if (haxe_ver >= 4)
|
||||
case OpIn: "in";
|
||||
#end
|
||||
default:
|
||||
continue;
|
||||
};
|
||||
binops.set(str, op);
|
||||
if( assign )
|
||||
@@ -92,6 +94,9 @@ class Macro {
|
||||
case OpNegBits: "~";
|
||||
case OpIncrement: "++";
|
||||
case OpDecrement: "--";
|
||||
#if (haxe_ver >= 4.2)
|
||||
case OpSpread: continue;
|
||||
#end
|
||||
}
|
||||
unops.set(str, op);
|
||||
}
|
||||
|
||||
+842
-477
File diff suppressed because it is too large
Load Diff
+27
-6
@@ -114,6 +114,25 @@ class Printer {
|
||||
return;
|
||||
}
|
||||
switch( #if hscriptPos e.e #else e #end ) {
|
||||
case EImport(c, n):
|
||||
add("import " + c);
|
||||
if(n != null)
|
||||
add(' as $n');
|
||||
case EClass(name, fields, extend, interfaces):
|
||||
add('class $name');
|
||||
if (extend != null)
|
||||
add(' extends $extend');
|
||||
for(_interface in interfaces) {
|
||||
add(' implements $_interface');
|
||||
}
|
||||
add(' {\n');
|
||||
tabs += "\t";
|
||||
//for(field in fields) {
|
||||
// expr(field);
|
||||
//}
|
||||
|
||||
tabs = tabs.substr(1);
|
||||
add("}");
|
||||
case EConst(c):
|
||||
switch( c ) {
|
||||
case CInt(i): add(i);
|
||||
@@ -122,7 +141,7 @@ class Printer {
|
||||
}
|
||||
case EIdent(v):
|
||||
add(v);
|
||||
case EVar(n, t, e):
|
||||
case EVar(n, t, e): // TODO: static, public, override
|
||||
add("var " + n);
|
||||
addType(t);
|
||||
if( e != null ) {
|
||||
@@ -145,9 +164,9 @@ class Printer {
|
||||
tabs = tabs.substr(1);
|
||||
add("}");
|
||||
}
|
||||
case EField(e, f):
|
||||
case EField(e, f, s):
|
||||
expr(e);
|
||||
add("." + f);
|
||||
add((s == true ? "?." : ".") + f);
|
||||
case EBinop(op, e1, e2):
|
||||
expr(e1);
|
||||
add(" " + op + " ");
|
||||
@@ -207,7 +226,7 @@ class Printer {
|
||||
add("break");
|
||||
case EContinue:
|
||||
add("continue");
|
||||
case EFunction(params, e, name, ret):
|
||||
case EFunction(params, e, name, ret): // TODO: static, public, override
|
||||
add("function");
|
||||
if( name != null )
|
||||
add(" " + name);
|
||||
@@ -234,7 +253,7 @@ class Printer {
|
||||
add("[");
|
||||
expr(index);
|
||||
add("]");
|
||||
case EArrayDecl(el):
|
||||
case EArrayDecl(el, _):
|
||||
add("[");
|
||||
var first = true;
|
||||
for( e in el ) {
|
||||
@@ -331,7 +350,7 @@ class Printer {
|
||||
|
||||
public static function errorToString( e : Expr.Error ) {
|
||||
var message = switch( #if hscriptPos e.e #else e #end ) {
|
||||
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF" : String.fromCharCode(c))+"' ("+c+")";
|
||||
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF (End Of File)" : String.fromCharCode(c))+"' ("+c+")";
|
||||
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
||||
case EUnterminatedString: "Unterminated string";
|
||||
case EUnterminatedComment: "Unterminated comment";
|
||||
@@ -341,6 +360,8 @@ class Printer {
|
||||
case EInvalidOp(op): "Invalid operator: "+op;
|
||||
case EInvalidAccess(f): "Invalid access to field " + f;
|
||||
case ECustom(msg): msg;
|
||||
case EInvalidClass(cla): "Invalid class: " + cla + " was not found.";
|
||||
case EAlreadyExistingClass(cla): 'Custom Class named $cla already exists.';
|
||||
};
|
||||
#if hscriptPos
|
||||
return e.origin + ":" + e.line + ": " + message;
|
||||
|
||||
@@ -27,6 +27,8 @@ class Tools {
|
||||
public static function iter( e : Expr, f : Expr -> Void ) {
|
||||
switch( expr(e) ) {
|
||||
case EConst(_), EIdent(_):
|
||||
case EImport(c): f(e);
|
||||
case EClass(_, e, _, _): for( a in e ) f(a);
|
||||
case EVar(_, _, e): if( e != null ) f(e);
|
||||
case EParent(e): f(e);
|
||||
case EBlock(el): for( e in el ) f(e);
|
||||
@@ -57,6 +59,7 @@ class Tools {
|
||||
if( def != null ) f(def);
|
||||
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
|
||||
case ECheckType(e,_): f(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +89,8 @@ class Tools {
|
||||
case ESwitch(e, cases, def): ESwitch(f(e), [for( c in cases ) { values : [for( v in c.values ) f(v)], expr : f(c.expr) } ], def == null ? null : f(def));
|
||||
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
|
||||
case ECheckType(e,t): ECheckType(f(e), t);
|
||||
case EImport(c): EImport(c);
|
||||
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
||||
}
|
||||
return mk(edef, e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
package hscript;
|
||||
|
||||
import Type.ValueType;
|
||||
import haxe.macro.ComplexTypeTools;
|
||||
#if macro
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Context;
|
||||
import haxe.macro.Printer;
|
||||
import haxe.macro.Compiler;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class UsingHandler {
|
||||
public var usedClass:Class<Dynamic>;
|
||||
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) {
|
||||
case TPath({name: "StdTypes"}):
|
||||
var a:TypePath = type.getParameters()[0];
|
||||
a.name = a.sub;
|
||||
a.sub = null;
|
||||
default:
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public static function setupMetas(shadowClass:TypeDefinition, imports) {
|
||||
shadowClass.meta = [{
|
||||
name: ':dox',
|
||||
pos: Context.currentPos(),
|
||||
params: [
|
||||
{
|
||||
expr: EConst(CIdent("hide")),
|
||||
pos: Context.currentPos()
|
||||
}
|
||||
]
|
||||
}];
|
||||
var module = Context.getModule(Context.getLocalModule());
|
||||
for(t in module) {
|
||||
switch(t) {
|
||||
case TInst(t, params):
|
||||
if (t != null) {
|
||||
var e = t.get();
|
||||
processModule(shadowClass, e.module, e.name);
|
||||
processImport(imports, e.module, e.name);
|
||||
}
|
||||
case TEnum(t, params):
|
||||
if (t != null) {
|
||||
var e = t.get();
|
||||
processModule(shadowClass, e.module, e.name);
|
||||
processImport(imports, e.module, e.name);
|
||||
}
|
||||
case TType(t, params):
|
||||
if (t != null) {
|
||||
var e = t.get();
|
||||
processModule(shadowClass, e.module, e.name);
|
||||
processImport(imports, e.module, e.name);
|
||||
}
|
||||
case TAbstract(t, params):
|
||||
if (t != null) {
|
||||
var e = t.get();
|
||||
processModule(shadowClass, e.module, e.name);
|
||||
processImport(imports, e.module, e.name);
|
||||
}
|
||||
default:
|
||||
// not needed?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function processModule(shadowClass:TypeDefinition, module:String, n:String) {
|
||||
if (n.endsWith("_Impl_"))
|
||||
n = n.substr(0, n.length - 6);
|
||||
if (module.endsWith("_Impl_"))
|
||||
module = module.substr(0, module.length - 6);
|
||||
|
||||
shadowClass.meta.push(
|
||||
{
|
||||
name: ':access',
|
||||
params: [
|
||||
Context.parse(fixModuleName(module.endsWith('.${n}') ? module : '${module}.${n}'), Context.currentPos())
|
||||
],
|
||||
pos: Context.currentPos()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*public static function getModuleName(path:Type) {
|
||||
switch(path) {
|
||||
case TPath(name, pack):// | TDClass(name, pack):
|
||||
var str = "";
|
||||
for(p in pack) {
|
||||
str += p + ".";
|
||||
}
|
||||
str += name;
|
||||
return str;
|
||||
|
||||
default:
|
||||
}
|
||||
return "INVALID";
|
||||
}*/
|
||||
|
||||
public static function fixModuleName(name:String) {
|
||||
return [for(s in name.split(".")) if (s.charAt(0) == "_") s.substr(1) else s].join(".");
|
||||
}
|
||||
public static function processImport(imports:Array<ImportExpr>, module:String, n:String) {
|
||||
if (n.endsWith("_Impl_"))
|
||||
n = n.substr(0, n.length - 6);
|
||||
module = fixModuleName(module);
|
||||
if (module.endsWith("_Impl_"))
|
||||
module = module.substr(0, module.length - 6);
|
||||
|
||||
imports.push({
|
||||
path: [for(m in module.split(".")) {
|
||||
name: m,
|
||||
pos: Context.currentPos()
|
||||
}],
|
||||
mode: INormal
|
||||
});
|
||||
}
|
||||
|
||||
public static function cleanExpr(expr:Expr, oldFunc:String, newFunc:String) {
|
||||
if (expr == null) return;
|
||||
if (expr.expr == null) return;
|
||||
switch(expr.expr) {
|
||||
case EConst(c):
|
||||
switch(c) {
|
||||
case CIdent(s):
|
||||
if (s == oldFunc)
|
||||
expr.expr = EConst(CIdent(newFunc));
|
||||
case CString(s, b):
|
||||
if (s == oldFunc)
|
||||
expr.expr = EConst(CString(s, b));
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
case EField(e, field):
|
||||
if (field == oldFunc && e != null) {
|
||||
switch(e.expr) {
|
||||
case EConst(c):
|
||||
switch(c) {
|
||||
case CIdent(s):
|
||||
if (s == "super")
|
||||
expr.expr = EField(e, newFunc);
|
||||
default:
|
||||
|
||||
}
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
case EParenthesis(e):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EObjectDecl(fields):
|
||||
for(f in fields) {
|
||||
cleanExpr(f.expr, oldFunc, newFunc);
|
||||
}
|
||||
case EArrayDecl(values):
|
||||
for(a in values) {
|
||||
cleanExpr(a, oldFunc, newFunc);
|
||||
}
|
||||
case ECall(e, params):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EBlock(exprs):
|
||||
for(e in exprs)
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EFor(it, expr):
|
||||
cleanExpr(it, oldFunc, newFunc);
|
||||
cleanExpr(expr, oldFunc, newFunc);
|
||||
case EIf(econd, eif, eelse):
|
||||
cleanExpr(econd, oldFunc, newFunc);
|
||||
cleanExpr(eif, oldFunc, newFunc);
|
||||
cleanExpr(eelse, oldFunc, newFunc);
|
||||
case EWhile(econd, e, normalWhile):
|
||||
cleanExpr(econd, oldFunc, newFunc);
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ECast(e, t):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ECheckType(e, t):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ETry(e, catches):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
for(c in catches) {
|
||||
cleanExpr(c.expr, oldFunc, newFunc);
|
||||
}
|
||||
case EThrow(e):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case ETernary(econd, eif, eelse):
|
||||
cleanExpr(econd, oldFunc, newFunc);
|
||||
cleanExpr(eif, oldFunc, newFunc);
|
||||
cleanExpr(eelse, oldFunc, newFunc);
|
||||
case ESwitch(e, cases, edef):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
for(c in cases) {
|
||||
cleanExpr(c.expr, oldFunc, newFunc);
|
||||
}
|
||||
cleanExpr(edef, oldFunc, newFunc);
|
||||
case EReturn(e):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EIs(e, t):
|
||||
cleanExpr(e, oldFunc, newFunc);
|
||||
case EVars(vars):
|
||||
for(v in vars) {
|
||||
cleanExpr(v.expr, oldFunc, newFunc);
|
||||
}
|
||||
case ENew(t, params):
|
||||
for(p in params) {
|
||||
cleanExpr(p, oldFunc, newFunc);
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
class UsingHandler {
|
||||
public var usedClass:Class<Dynamic>;
|
||||
public var className:String;
|
||||
}
|
||||
#end
|
||||
Reference in New Issue
Block a user