Compare commits

...
85 Commits
Author SHA1 Message Date
NeeEoo 2f2dec1634 Temp Fix for mod im working on 2023-08-13 12:02:04 +02:00
NeeEoo 51188173bb Merge To Main 2023-08-13 11:59:13 +02:00
NeeEoo d0797ad5d8 Fixed bug with redirects 2023-08-07 13:54:19 +02:00
NeeEoo 9b37bd532e Oops forgot this 2023-07-06 11:59:12 +02:00
NeeEoo 333352edcf Fix bug + bypassAccessor on assign on scriptObject 2023-07-06 00:40:21 +02:00
NeeEoo 05783773af Added support for sub class imports 2023-06-15 14:36:28 +02:00
NeeEoo 59ee20ee7a WIP Super Class Support 2023-06-15 14:21:18 +02:00
NeeEoo 87f2c1b062 Added import as and switch or and def null 2023-06-15 11:08:08 +02:00
NeeEoo b85cefea56 Cleanup 2023-04-19 13:37:08 +02:00
Yoshman29 2e28f863f3 some fixes & stuff 2023-04-19 01:46:48 +02:00
NeeEoo ddaa4d1741 Added support for dots in preprocessors 2023-04-10 15:08:16 +02:00
NeeEoo 732bd1520a Improved Custom Classes (getting fields outside of the class) 2023-04-10 14:14:16 +02:00
NeeEoo 1d67946f3f Outside variables now in classes (no more import in class) 2023-04-10 03:36:50 +02:00
Yoshman29 fab6d7e662 Merge branch 'custom-classes' of https://github.com/YoshiCrafter29/hscript-improved into custom-classes 2023-04-10 02:56:20 +02:00
NeeEoo 6e20578a81 Improved static variables 2023-04-10 02:37:41 +02:00
NeeEoo dc5282c32e Added finals 2023-04-10 02:10:46 +02:00
lunarcleint 812abae6e5 ??= op 2023-04-09 16:51:04 -07:00
NeeEoo b3b512d027 Added support for ?. 2023-04-10 00:09:50 +02:00
NeeEoo ed296c4c7f Merge branch 'master' into custom-classes 2023-04-09 23:28:45 +02:00
lunarcleint 595bb47249 ?? and .? syntax (only ?? is functional) 2023-04-09 14:09:58 -07:00
NeeEoo daad1a4fa8 Added underscore support to numbers + binary 2023-04-08 00:08:49 +02:00
Yoshman29 daef1ac198 Merge branch 'custom-classes' of https://github.com/YoshiCrafter29/hscript-improved into custom-classes 2023-04-07 16:40:23 +02:00
Yoshman29 3b9d88b252 Update Interp.hx 2023-04-07 16:40:22 +02:00
NeeEoo 809f8229b4 Implemented Super 2023-04-02 18:22:02 +02:00
Yoshman29 ffb1ee2523 Update CustomClassHandler.hx 2023-04-02 03:39:21 +02:00
Yoshman29 0903718314 removed all unnecessary traces 2023-04-01 22:46:02 +02:00
Yoshman29 e0cb883ae4 Update ClassExtendMacro.hx 2023-04-01 18:31:39 +02:00
Yoshman29 17449dd9d5 oopsie 2023-04-01 17:15:01 +02:00
Yoshman29 7963631a1d Update ClassExtendMacro.hx 2023-04-01 15:30:46 +02:00
Yoshman29 77d88f4b34 Update ClassExtendMacro.hx 2023-04-01 15:12:36 +02:00
Yoshman29 c5e3ab1162 custom classes 2023-04-01 15:02:36 +02:00
Yoshman29 75041c1db9 possible working code????? huh??? 2023-04-01 14:38:13 +02:00
Yoshman29 558a4c0782 Tried some fuckery 2023-04-01 02:23:07 +02:00
NeeEoo 995c3b9c8e ‍ 2023-03-31 22:11:48 +02:00
Yoshman29 0a64bca9ce custom class progress 2023-03-31 21:41:34 +02:00
NeeEoo b7b12b6cbb WIP Classes 2023-03-31 20:16:30 +02:00
NeeEoo 5684ca8671 WIP Class Parsing 2023-03-31 18:12:50 +02:00
NeeEoo 3c81360dc2 Merge branch 'master' into custom-classes 2023-03-31 17:03:00 +02:00
NeeEoo fc50ebdf90 Small Fix 2023-03-31 00:12:54 +02:00
Yoshman29 4d6e8db5ff helpers 2023-03-30 17:34:50 +02:00
NeeEoo 938ffac57e Custom classes, 2/? finished the macro 2023-03-19 17:57:37 +01:00
NeeEoo 50aaffb101 Custom classes, 1/? started with macros 2023-03-19 05:30:06 +01:00
NeeEoo 4f9b449c6e Added inferred map types and bypassAccessor 2023-03-19 05:26:27 +01:00
Yoshman29 c1a36a3f4b improve deez nuts 2023-01-07 22:22:05 +01:00
Yoshman29 4ca6e2a680 Fixed weird erroring with an error handling 2022-12-26 22:17:08 +01:00
Yoshman29 11db805c34 improve deez nuts 2022-12-24 13:07:02 +01:00
Yoshman29 f1f700ab69 Update UsingHandler.hx 2022-12-22 21:17:47 +01:00
Yoshman29 9eeb8ddb80 that macro took me 3 hours 2022-12-22 21:09:11 +01:00
Yoshman29 95de26a6d0 fuck 2022-12-09 23:09:28 +01:00
Yoshman29 88c2e28dbc crap 2022-12-07 23:51:03 +01:00
Yoshman29 30b7a9e4d4 Update Checker.hx 2022-12-07 23:47:37 +01:00
Yoshman29 37542065d6 bug fix (now it works as intended) 2022-11-04 20:10:35 +01:00
Yoshman29 c9608f7760 Update Interp.hx 2022-11-04 19:54:57 +01:00
Yoshman29 6ba54b0e77 static and public 2022-11-04 19:33:04 +01:00
Yoshman29 f9bb3105c8 new interface 2022-11-02 14:36:36 +01:00
Yoshman29 4b5baa9b5f Revert "thing that needs to be reverted"
This reverts commit 6dedd87260.
2022-10-13 23:18:54 +02:00
Yoshman29 6dedd87260 thing that needs to be reverted 2022-10-13 23:18:47 +02:00
Yoshman29 91317222fb Update Interp.hx 2022-08-13 03:00:11 +02:00
Yoshman29 494953a8cc Added interp.importEnabled 2022-08-12 23:40:55 +02:00
Yoshman29 ae4d8be50c more error handling + variables fix 2022-08-10 17:21:15 +02:00
Yoshman29 d34790e05c fix 2022-07-19 02:44:22 +02:00
Yoshman29 b77e15c6d6 forgot to push smh 2022-07-11 11:32:45 +02:00
Yoshman29 54195d5811 hscript updates 2022-07-02 18:21:43 +02:00
Yoshman29 9c7907f91a fixes 2022-06-30 02:03:07 +02:00
Yoshman29 0601b8def6 natural import & static access from vars for YCE 2022-06-29 00:53:51 +02:00
YoshiCrafter29 841261f199 Added import support 2022-06-08 20:10:40 +02:00
Nicolas Cannasse 7124b6c4ce fix for latest haxe 2022-04-11 17:14:38 +02:00
Nicolas Cannasse ad7beec559 fix for async idents and local functions 2022-04-01 14:43:03 +02:00
Nicolas Cannasse bd4fc51392 renamed test script 2022-04-01 10:27:20 +02:00
Nicolas Cannasse 54d994a879 added asyncIdents support 2022-03-24 15:26:50 +01:00
Nicolas Cannasse 891a085f2b fixed declared vars leak when return (close #111) 2022-01-30 11:26:32 +01:00
Nicolas Cannasse e7ccd2e72d another {} unify fix 2021-05-14 18:22:16 +02:00
Nicolas Cannasse 459a39e65d fix unification with {} 2021-05-14 18:18:55 +02:00
Jens FischerandGitHub 36eb0fca8b Fix Std.is() deprecation warnings with Haxe 4.2 (#101) 2021-03-15 19:49:07 +01:00
Nicolas Cannasse 53b9e22f26 fix for haxe 4.2 2021-02-11 12:07:30 +01:00
Nicolas Cannasse 8ff3f5e351 fixed getFields (apply params, handle interfaces) and getField (handle interface inheritance) 2020-12-18 15:58:21 +01:00
Nicolas Cannasse e6a2c443cb added support for interfaces type checking 2020-12-04 17:08:41 +01:00
Nicolas Cannasse 4f25ab162d added inheritance on setGlobals 2020-08-26 15:51:27 +02:00
Nicolas Cannasse 0520d9f187 added setVar (allow to define globals set behavior) 2020-07-30 10:22:48 +02:00
Nicolas Cannasse cc3c21b7e3 fixed unop priority overriding binop one (close #94) 2020-07-14 12:49:24 +02:00
Nicolas Cannasse ae9560124e fixed () -> e short lambda parsing (close #93) 2020-05-07 10:24:04 +02:00
Nicolas Cannasse 085f4ec37e fixed comments parsing was broken by previous fix 2020-04-27 11:19:46 +02:00
Nicolas Cannasse 476c3a9cc9 fixed parser with concat binop/unop such as a<-b or a<++b (close #92) 2020-04-26 15:10:00 +02:00
Mark KnolandGitHub 1bc5ac8768 Update haxelib.json (#83) 2020-04-12 21:32:39 +02:00
Nicolas Cannasse 4bdff11b87 removed 2020-04-10 12:21:54 +02:00
17 changed files with 2207 additions and 1046 deletions
+5 -2
View File
@@ -7,7 +7,7 @@ import hscript.Printer;
import hscript.Checker; import hscript.Checker;
import haxe.unit.*; import haxe.unit.*;
class Test extends TestCase { class TestHScript extends TestCase {
function assertScript(x,v:Dynamic,?vars : Dynamic, allowTypes=false, ?pos:haxe.PosInfos) { function assertScript(x,v:Dynamic,?vars : Dynamic, allowTypes=false, ?pos:haxe.PosInfos) {
var p = new hscript.Parser(); var p = new hscript.Parser();
p.allowTypes = allowTypes; p.allowTypes = allowTypes;
@@ -101,6 +101,7 @@ class Test extends TestCase {
assertScript("/**/0", 0); assertScript("/**/0", 0);
assertScript("x=1;x*=-2", -2); assertScript("x=1;x*=-2", -2);
assertScript("var f = x -> x + 1; f(3)", 4); 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) -> x + 1; f(3)", 4);
assertScript("var f = (x:Int) -> 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); 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)->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)->(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 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 { function testMap():Void {
@@ -170,7 +173,7 @@ class Test extends TestCase {
#end #end
var runner = new TestRunner(); var runner = new TestRunner();
runner.add(new Test()); runner.add(new TestHScript());
var succeed = runner.run(); var succeed = runner.run();
#if sys #if sys
+1 -1
View File
@@ -1,3 +1,3 @@
-main Test -main TestHScript
-dce no -dce no
-lib hx3compat -lib hx3compat
+1 -1
View File
@@ -5,5 +5,5 @@
"description": "Haxe Script is a scripting engine for a subset of the Haxe language", "description": "Haxe Script is a scripting engine for a subset of the Haxe language",
"version": "2.4.0", "version": "2.4.0",
"releasenote": "Haxe 4.0 final + type checking/completion (hscript.Checker)", "releasenote": "Haxe 4.0 final + type checking/completion (hscript.Checker)",
"contributors": ["ncannasse"] "contributors": ["ncannasse","HaxeFoundation"]
} }
-65
View File
@@ -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
View File
@@ -36,6 +36,7 @@ class Async {
var currentLoop : Expr; var currentLoop : Expr;
var currentBreak : Expr -> Expr; var currentBreak : Expr -> Expr;
var uid = 0; 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 nullExpr : Expr = #if hscriptPos { e : null, pmin : 0, pmax : 0, origin : "<null>", line : 0 } #else null #end;
static var nullId = mk(EIdent("null"), nullExpr); static var nullId = mk(EIdent("null"), nullExpr);
@@ -207,11 +208,17 @@ class Async {
return syncFlag; return syncFlag;
} }
inline function isAsyncIdent( id : String ) {
return asyncIdents == null || asyncIdents.exists(id);
}
function checkSync( e : Expr ) { function checkSync( e : Expr ) {
if( !syncFlag ) if( !syncFlag )
return; return;
switch( expr(e) ) { 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; syncFlag = false;
case EFunction(_,_,name,_) if( name != null ): case EFunction(_,_,name,_) if( name != null ):
syncFlag = false; syncFlag = false;
+4
View File
@@ -140,6 +140,10 @@ class Bytes {
#end #end
bout.addByte(Type.enumIndex(e)); bout.addByte(Type.enumIndex(e));
switch( e ) { switch( e ) {
case EImport(c):
// TODO
case EClass(_, _, _, _):
// TODO
case EConst(c): case EConst(c):
doEncodeConst(c); doEncodeConst(c);
case EIdent(v): case EIdent(v):
+67 -10
View File
@@ -48,6 +48,8 @@ typedef CNamedType = {
typedef CClass = {> CNamedType, typedef CClass = {> CNamedType,
@:optional var superClass : TType; @:optional var superClass : TType;
@:optional var constructor : CField; @:optional var constructor : CField;
@:optional var interfaces : Array<TType>;
@:optional var isInterface : Bool;
var fields : Map<String,CField>; var fields : Map<String,CField>;
var statics : Map<String,CField>; var statics : Map<String,CField>;
} }
@@ -121,12 +123,19 @@ class CheckerTypes {
fields : new Map(), fields : new Map(),
statics : new Map(), statics : new Map(),
}; };
if( c.isInterface )
cl.isInterface = true;
for( p in c.params ) for( p in c.params )
cl.params.push(TParam(p)); cl.params.push(TParam(p));
todo.push(function() { todo.push(function() {
localParams = [for( t in cl.params ) c.path+"."+Checker.typeStr(t) => t]; localParams = [for( t in cl.params ) c.path+"."+Checker.typeStr(t) => t];
if( c.superClass != null ) if( c.superClass != null )
cl.superClass = getType(c.superClass.path, [for( t in c.superClass.params ) makeXmlType(t)]); 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 = []; var pkeys = [];
for( f in c.fields ) { for( f in c.fields ) {
if( f.isOverride || f.name.substr(0,4) == "get_" || f.name.substr(0,4) == "set_" ) continue; 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 ) { public function setGlobals( cl : CClass ) {
while( true ) {
for( f in cl.fields ) for( f in cl.fields )
if( f.isPublic ) 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()]))); 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 ) { public function removeGlobal( name : String ) {
@@ -580,6 +597,8 @@ class Checker {
case [TDynamic, _]: case [TDynamic, _]:
return true; return true;
case [TAnon(a1),TAnon(a2)]: case [TAnon(a1),TAnon(a2)]:
if( a2.length == 0 ) // always unify with {}
return true;
var m = new Map(); var m = new Map();
for( f in a1 ) for( f in a1 )
m.set(f.name, f); m.set(f.name, f);
@@ -595,6 +614,18 @@ class Checker {
return true; return true;
case [TInst(cl1,pl1), TInst(cl2,pl2)]: case [TInst(cl1,pl1), TInst(cl2,pl2)]:
while( cl1 != cl2 ) { 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 ) { switch( cl1.superClass ) {
case null: return false; case null: return false;
case TInst(c, args): case TInst(c, args):
@@ -693,24 +724,43 @@ class Checker {
} }
} }
public function getFields( t : TType ) { public function getFields( t : TType ) : Array<{ name : String, t : TType }> {
var fields = []; var fields = [];
while( t != null ) { switch( follow(t) ) {
t = follow(t);
switch( t ) {
case TInst(c, args): case TInst(c, args):
var map = (t) -> apply(t,c.params,args);
while( c != null ) {
for( fname in c.fields.keys() ) { for( fname in c.fields.keys() ) {
var f = c.fields.get(fname); 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): case TAnon(fl):
for( f in fl ) for( f in fl )
fields.push({ name : f.name, t : f.t }); fields.push({ name : f.name, t : f.t });
break;
default: default:
} }
}
return fields; return fields;
} }
@@ -726,6 +776,13 @@ class Checker {
if( cf.t == null ) cf = null; 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( cf == null ) {
if( c.superClass == null ) return null; if( c.superClass == null ) return null;
var ft = getField(c.superClass, f, e, forWrite); var ft = getField(c.superClass, f, e, forWrite);
@@ -917,7 +974,7 @@ class Checker {
return TVoid; return TVoid;
case EObject(fl): case EObject(fl):
switch( withType ) { 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]; var map = [for( f in tfields ) f.name => f];
return TAnon([for( f in fl ) { return TAnon([for( f in fl ) {
var ft = map.get(f.name); var ft = map.get(f.name);
@@ -930,7 +987,7 @@ class Checker {
default: default:
return TAnon([for( f in fl ) { t : typeExpr(f.e, Value), opt : false, name : f.name }]); 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; return TVoid;
case EReturn(v): case EReturn(v):
var et = v == null ? TVoid : typeExpr(v, allowReturn == null ? Value : WithType(allowReturn)); var et = v == null ? TVoid : typeExpr(v, allowReturn == null ? Value : WithType(allowReturn));
+105
View File
@@ -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
View File
@@ -45,10 +45,10 @@ enum Expr {
#end #end
EConst( c : Const ); EConst( c : Const );
EIdent( v : String ); EIdent( v : String );
EVar( n : String, ?t : CType, ?e : Expr ); EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
EParent( e : Expr ); EParent( e : Expr );
EBlock( e : Array<Expr> ); EBlock( e : Array<Expr> );
EField( e : Expr, f : String ); EField( e : Expr, f : String , ?safe : Bool );
EBinop( op : String, e1 : Expr, e2 : Expr ); EBinop( op : String, e1 : Expr, e2 : Expr );
EUnop( op : String, prefix : Bool, e : Expr ); EUnop( op : String, prefix : Bool, e : Expr );
ECall( e : Expr, params : Array<Expr> ); ECall( e : Expr, params : Array<Expr> );
@@ -57,19 +57,22 @@ enum Expr {
EFor( v : String, it : Expr, e : Expr ); EFor( v : String, it : Expr, e : Expr );
EBreak; EBreak;
EContinue; 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 ); EReturn( ?e : Expr );
EArray( e : Expr, index : Expr ); EArray( e : Expr, index : Expr );
EArrayDecl( e : Array<Expr> ); EArrayDecl( e : Array<Expr>, ?wantedType: CType );
ENew( cl : String, params : Array<Expr> ); ENew( cl : String, params : Array<Expr> );
EThrow( e : Expr ); EThrow( e : Expr );
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr ); ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
EObject( fl : Array<{ name : String, e : Expr }> ); EObject( fl : Array<{ name : String, e : Expr }> );
ETernary( cond : Expr, e1 : Expr, e2 : 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); EDoWhile( cond : Expr, e : Expr);
EMeta( name : String, args : Array<Expr>, e : Expr ); EMeta( name : String, args : Array<Expr>, e : Expr );
ECheckType( e : Expr, t : CType ); 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 }; typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
@@ -117,6 +120,8 @@ enum Error {
EInvalidOp( op : String ); EInvalidOp( op : String );
EInvalidAccess( f : String ); EInvalidAccess( f : String );
ECustom( msg : String ); ECustom( msg : String );
EInvalidClass( className : String);
EAlreadyExistingClass( className : String);
} }
+6
View File
@@ -0,0 +1,6 @@
package hscript;
interface IHScriptCustomBehaviour {
public function hset(name:String, val:Dynamic):Dynamic;
public function hget(name:String):Dynamic;
}
+5
View File
@@ -0,0 +1,5 @@
package hscript;
interface IHScriptCustomConstructor {
public function hnew(args:Array<Dynamic>):Dynamic;
}
+578 -248
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -79,6 +79,8 @@ class Macro {
#if (haxe_ver >= 4) #if (haxe_ver >= 4)
case OpIn: "in"; case OpIn: "in";
#end #end
default:
continue;
}; };
binops.set(str, op); binops.set(str, op);
if( assign ) if( assign )
@@ -92,6 +94,9 @@ class Macro {
case OpNegBits: "~"; case OpNegBits: "~";
case OpIncrement: "++"; case OpIncrement: "++";
case OpDecrement: "--"; case OpDecrement: "--";
#if (haxe_ver >= 4.2)
case OpSpread: continue;
#end
} }
unops.set(str, op); unops.set(str, op);
} }
+398 -33
View File
@@ -32,6 +32,7 @@ enum Token {
TBrOpen; TBrOpen;
TBrClose; TBrClose;
TDot; TDot;
TQuestionDot;
TComma; TComma;
TSemicolon; TSemicolon;
TBkOpen; TBkOpen;
@@ -51,11 +52,9 @@ class Parser {
#if haxe3 #if haxe3
public var opPriority : Map<String,Int>; public var opPriority : Map<String,Int>;
public var opRightAssoc : Map<String,Bool>; public var opRightAssoc : Map<String,Bool>;
public var unops : Map<String,Bool>; // true if allow postfix
#else #else
public var opPriority : Hash<Int>; public var opPriority : Hash<Int>;
public var opRightAssoc : Hash<Bool>; public var opRightAssoc : Hash<Bool>;
public var unops : Hash<Bool>; // true if allow postfix
#end #end
/** /**
@@ -92,6 +91,8 @@ class Parser {
var idents : Array<Bool>; var idents : Array<Bool>;
var uid : Int = 0; var uid : Int = 0;
var disableOrOp : Bool = false;
#if hscriptPos #if hscriptPos
var origin : String; var origin : String;
var tokenMin : Int; var tokenMin : Int;
@@ -111,7 +112,6 @@ class Parser {
#end #end
public function new() { public function new() {
line = 1; line = 1;
opChars = "+*/-=!><&|^%~"; opChars = "+*/-=!><&|^%~";
@@ -126,24 +126,24 @@ class Parser {
["..."], ["..."],
["&&"], ["&&"],
["||"], ["||"],
["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^=","=>"], ["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^=","=>","??="],
["->", "??"],
["is"]
]; ];
#if haxe3 #if haxe3
opPriority = new Map(); opPriority = new Map();
opRightAssoc = new Map(); opRightAssoc = new Map();
unops = new Map();
#else #else
opPriority = new Hash(); opPriority = new Hash();
opRightAssoc = new Hash(); opRightAssoc = new Hash();
unops = new Hash();
#end #end
for( i in 0...priorities.length ) for( i in 0...priorities.length )
for( x in priorities[i] ) { for( x in priorities[i] ) {
opPriority.set(x, i); opPriority.set(x, i);
if( i == 9 ) opRightAssoc.set(x, true); if( i == 9 ) opRightAssoc.set(x, true);
} }
for( x in ["!", "++", "--", "-", "~"] ) for( x in ["!", "++", "--", "~"] ) // unary "-" handled in parser directly!
unops.set(x, x == "++" || x == "--"); opPriority.set(x, x == "++" || x == "--" ? -1 : -2);
} }
public inline function error( err, pmin, pmax ) { public inline function error( err, pmin, pmax ) {
@@ -279,8 +279,9 @@ class Parser {
if( e == null ) return false; if( e == null ) return false;
return switch( expr(e) ) { return switch( expr(e) ) {
case EBlock(_), EObject(_), ESwitch(_): true; case EBlock(_), EObject(_), ESwitch(_): true;
case EFunction(_,e,_,_): isBlock(e); case EFunction(_,e,_,_,_,_): isBlock(e);
case EVar(_, t, e): e != null ? isBlock(e) : t != null ? t.match(CTAnon(_)) : false; case EClass(_,e,_,_): true;
case EVar(_, t, e, _,_): e != null ? isBlock(e) : t != null ? t.match(CTAnon(_)) : false;
case EIf(_,e1,e2): if( e2 != null ) isBlock(e2) else isBlock(e1); case EIf(_,e1,e2): if( e2 != null ) isBlock(e2) else isBlock(e1);
case EBinop(_,_,e): isBlock(e); case EBinop(_,_,e): isBlock(e);
case EUnop(_,prefix,e): !prefix && isBlock(e); case EUnop(_,prefix,e): !prefix && isBlock(e);
@@ -350,20 +351,32 @@ class Parser {
} }
function parseExpr() { function parseExpr() {
var oldPos = readPos;
var tk = token(); var tk = token();
#if hscriptPos #if hscriptPos
var p1 = tokenMin; var p1 = tokenMin;
#end #end
switch( tk ) { switch( tk ) {
case TId(id): case TId(id):
var e = parseStructure(id); var e = parseStructure(id, oldPos);
if( e == null ) if( e == null )
e = mk(EIdent(id)); e = mk(EIdent(id));
return parseExprNext(e); return parseExprNext(e);
case TConst(c): case TConst(c):
return parseExprNext(mk(EConst(c))); return parseExprNext(mk(EConst(c)));
case TPOpen: case TPOpen:
tk = token();
if( tk == TPClose ) {
ensureToken(TOp("->"));
var eret = parseExpr();
return mk(EFunction([], mk(EReturn(eret),p1)), p1);
}
push(tk);
var oldoo = disableOrOp;
disableOrOp = false;
var e = parseExpr(); var e = parseExpr();
disableOrOp = oldoo;
tk = token(); tk = token();
switch( tk ) { switch( tk ) {
case TPClose: case TPClose:
@@ -433,31 +446,40 @@ class Parser {
} }
return mk(EBlock(a),p1); return mk(EBlock(a),p1);
case TOp(op): case TOp(op):
if( unops.exists(op) ) { if( op == "-" ) {
var start = tokenMin; var start = tokenMin;
var oldoo = disableOrOp;
disableOrOp = false;
var e = parseExpr(); var e = parseExpr();
if( op == "-" && e != null ) disableOrOp = oldoo;
if( e == null )
return makeUnop(op,e);
switch( expr(e) ) { switch( expr(e) ) {
case EConst(CInt(i)): case EConst(CInt(i)):
return mk(EConst(CInt(-i)), start, pmax(e)); return mk(EConst(CInt(-i)), start, pmax(e));
case EConst(CFloat(f)): case EConst(CFloat(f)):
return mk(EConst(CFloat(-f)), start, pmax(e)); return mk(EConst(CFloat(-f)), start, pmax(e));
default: default:
}
return makeUnop(op,e); return makeUnop(op,e);
} }
}
if( opPriority.get(op) < 0 )
return makeUnop(op,parseExpr());
return unexpected(tk); return unexpected(tk);
case TBkOpen: case TBkOpen:
var a = new Array(); var a = new Array();
tk = token(); tk = token();
while( tk != TBkClose && (!resumeErrors || tk != TEof) ) { while( tk != TBkClose && (!resumeErrors || tk != TEof) ) {
push(tk); push(tk);
var oldoo = disableOrOp;
disableOrOp = false;
a.push(parseExpr()); a.push(parseExpr());
disableOrOp = oldoo;
tk = token(); tk = token();
if( tk == TComma ) if( tk == TComma )
tk = token(); tk = token();
} }
if( a.length == 1 && a[0] != null ) if( a.length == 1 && a[0] != null ) // What is this for???
switch( expr(a[0]) ) { switch( expr(a[0]) ) {
case EFor(_), EWhile(_), EDoWhile(_): case EFor(_), EWhile(_), EDoWhile(_):
var tmp = "__a_" + (uid++); var tmp = "__a_" + (uid++);
@@ -469,7 +491,7 @@ class Parser {
return parseExprNext(e); return parseExprNext(e);
default: default:
} }
return parseExprNext(mk(EArrayDecl(a), p1)); return parseExprNext(mk(EArrayDecl(a, nextType), p1));
case TMeta(id) if( allowMetadata ): case TMeta(id) if( allowMetadata ):
var args = parseMetaArgs(); var args = parseMetaArgs();
return mk(EMeta(id, args, parseExpr()),p1); return mk(EMeta(id, args, parseExpr()),p1);
@@ -572,7 +594,11 @@ class Parser {
} }
} }
function parseStructure(id) { var nextIsOverride:Bool = false;
var nextIsStatic:Bool = false;
var nextIsPublic:Bool = false;
var nextType:CType = null;
function parseStructure(id, ?oldPos:Int) {
#if hscriptPos #if hscriptPos
var p1 = tokenMin; var p1 = tokenMin;
#end #end
@@ -596,20 +622,111 @@ class Parser {
if( semic ) push(TSemicolon); if( semic ) push(TSemicolon);
} }
mk(EIf(cond,e1,e2),p1,(e2 == null) ? tokenMax : pmax(e2)); mk(EIf(cond,e1,e2),p1,(e2 == null) ? tokenMax : pmax(e2));
case "var": case "override":
nextIsOverride = true;
var nextToken = token();
switch(nextToken) {
case TId("public"):
var str = parseStructure("public"); // override public
nextIsOverride = false;
str;
case TId("function"):
var str = parseStructure("function"); // override function
nextIsOverride = false;
str;
case TId("static"):
var str = parseStructure("static"); // override static
nextIsOverride = false;
str;
case TId("var"):
var str = parseStructure("var"); // override var
nextIsOverride = false;
str;
case TId("final"):
var str = parseStructure("final"); // override final
nextIsOverride = false;
str;
default:
unexpected(nextToken);
nextIsOverride = false;
null;
}
case "static":
nextIsStatic = true;
var nextToken = token();
switch(nextToken) {
case TId("public"):
var str = parseStructure("public"); // static public
nextIsStatic = false;
str;
case TId("function"):
var str = parseStructure("function"); // static function
nextIsStatic = false;
str;
case TId("override"):
var str = parseStructure("override"); // static override
nextIsStatic = false;
str;
case TId("var"):
var str = parseStructure("var"); // static var
nextIsStatic = false;
str;
case TId("final"):
var str = parseStructure("final"); // static final
nextIsStatic = false;
str;
default:
unexpected(nextToken);
nextIsStatic = false;
null;
}
case "public":
nextIsPublic = true;
var nextToken = token();
switch(nextToken) {
case TId("static"):
var str = parseStructure("static"); // public static
nextIsPublic = false;
str;
case TId("function"):
var str = parseStructure("function"); // public function
nextIsPublic = false;
str;
case TId("override"):
var str = parseStructure("override"); // public override
nextIsPublic = false;
str;
case TId("var"):
var str = parseStructure("var"); // public var
nextIsPublic = false;
str;
case TId("final"):
var str = parseStructure("final"); // public final
nextIsPublic = false;
str;
default:
unexpected(nextToken);
nextIsPublic = false;
null;
}
case "var" | "final":
var ident = getIdent(); var ident = getIdent();
var tk = token(); var tk = token();
var t = null; var t = null;
nextType = null;
if( tk == TDoubleDot && allowTypes ) { if( tk == TDoubleDot && allowTypes ) {
t = parseType(); t = parseType();
tk = token(); tk = token();
nextType = t;
} }
var e = null; var e = null;
if( Type.enumEq(tk,TOp("=")) ) if( Type.enumEq(tk,TOp("=")) )
e = parseExpr(); e = parseExpr();
else else
push(tk); push(tk);
mk(EVar(ident,t,e),p1,(e == null) ? tokenMax : pmax(e)); nextType = null;
mk(EVar(ident, t, e, nextIsPublic, nextIsStatic), p1, (e == null) ? tokenMax : pmax(e));
case "while": case "while":
var econd = parseExpr(); var econd = parseExpr();
var e = parseExpr(); var e = parseExpr();
@@ -646,7 +763,150 @@ class Parser {
default: push(tk); default: push(tk);
} }
var inf = parseFunctionDecl(); var inf = parseFunctionDecl();
mk(EFunction(inf.args, inf.body, name, inf.ret),p1,pmax(inf.body));
var tk = token();
push(tk);
mk(EFunction(inf.args, inf.body, name, inf.ret, nextIsPublic, nextIsStatic, nextIsOverride),p1,pmax(inf.body));
case "import":
var oldReadPos = readPos;
var tk = token();
switch( tk ) {
case TPOpen:
var tok = token();
switch(tok) {
case TConst(c):
switch(c) {
case CString(s):
token();
ensure(TSemicolon);
push(TSemicolon);
mk(EImport(s), p1);
default:
unexpected(tok);
null;
}
default:
unexpected(tok);
null;
}
case TId(id):
var path = [id];
var asname:String = null;
var t = null;
while( true ) {
t = token();
if( t != TDot ) {
if(t.match(TId("as"))) {
t = token();
switch( t ) {
case TId(id):
asname = id;
default:
unexpected(t);
}
break;
}
push(t);
break;
}
t = token();
switch( t ) {
case TId(id):
path.push(id);
default:
unexpected(t);
}
}
ensure(TSemicolon);
push(TSemicolon);
var p = path.join(".");
mk(EImport(p, asname),p1);
default:
unexpected(tk);
null;
}
case "class":
// example: class ClassName
var tk = token();
var name = null;
switch (tk) {
case TId(id): name = id;
default: push(tk);
}
var extend:String = null;
var interfaces:Array<String> = [];
// optional - example: extends BaseClass
while( true ) {
var t = token();
switch( t ) {
case TId("extends"):
var e = parseType();
switch(e) {
case CTPath(path, params):
if(extend != null) {
error(ECustom('Cannot extend a class twice.'), 0, 0);
}
extend = path.join(".");
default:
error(ECustom('${Std.string(e)} is not a valid path.'), 0, 0);
}
default:
push(t);
break;
}
}
/*while(true) {
tk = token();
trace(tk);
switch (tk) {
case TId(id):
if (id == "extends") {
tk = token();
if(extend != null) {
unexpected(tk);
} else {
switch (tk) {
case TId(id): extend = id;
default: unexpected(tk);
}
}
} else if (id == "implements") {
tk = token();
switch (tk) {
case TId(id): interfaces.push(id);
default: unexpected(tk);
}
} else {
//push(tk);
}
case TBrOpen:
push(tk);
break;
default:
//push(tk);
}
}*/
var fields = [];
ensure(TBrOpen);
while( !maybe(TBrClose) ) {
if(token() == TSemicolon) continue;
var a = parseExpr();
fields.push(a);
}
var tk = token();
push(tk);
mk(EClass(name, fields, extend, interfaces), p1);
case "return": case "return":
var tk = token(); var tk = token();
push(tk); push(tk);
@@ -668,7 +928,7 @@ class Parser {
} }
} }
var args = parseExprList(TPClose); var args = parseExprList(TPClose);
mk(ENew(a.join("."),args),p1); mk(ENew(a.join("."), args), p1);
case "throw": case "throw":
var e = parseExpr(); var e = parseExpr();
mk(EThrow(e),p1,pmax(e)); mk(EThrow(e),p1,pmax(e));
@@ -696,12 +956,13 @@ class Parser {
case TId("case"): case TId("case"):
var c = { values : [], expr : null }; var c = { values : [], expr : null };
cases.push(c); cases.push(c);
disableOrOp = true;
while( true ) { while( true ) {
var e = parseExpr(); var e = parseExpr();
c.values.push(e); c.values.push(e);
tk = token(); tk = token();
switch( tk ) { switch( tk ) {
case TComma: case TComma | TOp("|"):
// next expr // next expr
case TDoubleDot: case TDoubleDot:
break; break;
@@ -710,6 +971,7 @@ class Parser {
break; break;
} }
} }
disableOrOp = false;
var exprs = []; var exprs = [];
while( true ) { while( true ) {
tk = token(); tk = token();
@@ -783,7 +1045,12 @@ class Parser {
unexpected(tk); unexpected(tk);
} }
if( unops.get(op) ) { if(disableOrOp && op == "|") {
push(tk);
return e1;
}
if( opPriority.get(op) == -1 ) {
if( isBlock(e1) || switch(expr(e1)) { case EParent(_): true; default: false; } ) { if( isBlock(e1) || switch(expr(e1)) { case EParent(_): true; default: false; } ) {
push(tk); push(tk);
return e1; return e1;
@@ -791,9 +1058,9 @@ class Parser {
return parseExprNext(mk(EUnop(op,false,e1),pmin(e1))); return parseExprNext(mk(EUnop(op,false,e1),pmin(e1)));
} }
return makeBinop(op,e1,parseExpr()); return makeBinop(op,e1,parseExpr());
case TDot: case TDot | TQuestionDot:
var field = getIdent(); var field = getIdent();
return parseExprNext(mk(EField(e1,field),pmin(e1))); return parseExprNext(mk(EField(e1, field, tk == TQuestionDot), pmin(e1)));
case TPOpen: case TPOpen:
return parseExprNext(mk(ECall(e1,parseExprList(TPClose)),pmin(e1))); return parseExprNext(mk(ECall(e1,parseExprList(TPClose)),pmin(e1)));
case TBkOpen: case TBkOpen:
@@ -836,8 +1103,10 @@ class Parser {
if( allowTypes ) { if( allowTypes ) {
if( maybe(TDoubleDot) ) if( maybe(TDoubleDot) )
arg.t = parseType(); arg.t = parseType();
if( maybe(TOp("=")) ) if( maybe(TOp("="))) {
arg.value = parseExpr(); arg.value = parseExpr();
arg.opt = true;
}
} }
tk = token(); tk = token();
switch( tk ) { switch( tk ) {
@@ -979,6 +1248,14 @@ class Parser {
fields.push( { name : name, t : parseType(), meta : meta } ); fields.push( { name : name, t : parseType(), meta : meta } );
meta = null; meta = null;
ensure(TSemicolon); ensure(TSemicolon);
case TId("final"):
var name = getIdent();
ensure(TDoubleDot);
if( meta == null ) meta = [];
meta.push({ name : ":final", params : [] });
fields.push( { name : name, t : parseType(), meta : meta } );
meta = null;
ensure(TSemicolon);
case TId(name): case TId(name):
ensure(TDoubleDot); ensure(TDoubleDot);
fields.push( { name : name, t : parseType(), meta : meta } ); fields.push( { name : name, t : parseType(), meta : meta } );
@@ -1314,18 +1591,25 @@ class Parser {
return b.toString(); return b.toString();
} }
function token() { function token(?infos : Null<haxe.PosInfos>) {
//function ttrace(v:Dynamic, ?infos : Null<haxe.PosInfos>) {
// Sys.print(infos.fileName+":"+infos.lineNumber+": " + Std.string(v));
// Sys.print("\r\n");
//}
#if hscriptPos #if hscriptPos
var t = tokens.pop(); var t = tokens.pop();
if( t != null ) { if( t != null ) {
tokenMin = t.min; tokenMin = t.min;
tokenMax = t.max; tokenMax = t.max;
//ttrace(t.t, infos);
return t.t; return t.t;
} }
oldTokenMin = tokenMin; oldTokenMin = tokenMin;
oldTokenMax = tokenMax; oldTokenMax = tokenMax;
tokenMin = (this.char < 0) ? readPos : readPos - 1; tokenMin = (this.char < 0) ? readPos : readPos - 1;
var t = _token(); var t = _token();
//ttrace(t, infos);
tokenMax = (this.char < 0) ? readPos - 1 : readPos - 2; tokenMax = (this.char < 0) ? readPos - 1 : readPos - 2;
return t; return t;
} }
@@ -1367,6 +1651,7 @@ class Parser {
switch( char ) { switch( char ) {
case 48,49,50,51,52,53,54,55,56,57: case 48,49,50,51,52,53,54,55,56,57:
n = n * 10 + (char - 48); n = n * 10 + (char - 48);
case '_'.code:
case "e".code, "E".code: case "e".code, "E".code:
var tk = token(); var tk = token();
var pow : Null<Int> = null; var pow : Null<Int> = null;
@@ -1410,6 +1695,7 @@ class Parser {
n = (n << 4) + (char - 55); n = (n << 4) + (char - 55);
case 97,98,99,100,101,102: // a-f case 97,98,99,100,101,102: // a-f
n = (n << 4) + (char - 87); n = (n << 4) + (char - 87);
case '_'.code:
default: default:
this.char = char; this.char = char;
return TConst(CInt(n)); return TConst(CInt(n));
@@ -1426,6 +1712,7 @@ class Parser {
n = haxe.Int32.add(haxe.Int32.shl(n,4), cast (char - 55)); n = haxe.Int32.add(haxe.Int32.shl(n,4), cast (char - 55));
case 97,98,99,100,101,102: // a-f case 97,98,99,100,101,102: // a-f
n = haxe.Int32.add(haxe.Int32.shl(n,4), cast (char - 87)); n = haxe.Int32.add(haxe.Int32.shl(n,4), cast (char - 87));
case '_'.code:
default: default:
this.char = char; this.char = char;
// we allow to parse hexadecimal Int32 in Neko, but when the value will be // we allow to parse hexadecimal Int32 in Neko, but when the value will be
@@ -1436,6 +1723,41 @@ class Parser {
} }
} }
#end #end
case "b".code: // Custom thing, not supported in haxe
if( n > 0 || exp > 0 )
invalidChar(char);
// read binary
#if haxe3
var n = 0;
while( true ) {
char = readChar();
switch( char ) {
case 48,49: // 0-1
n = (n << 1) + char - 48;
case '_'.code:
default:
this.char = char;
return TConst(CInt(n));
}
}
#else
var n = haxe.Int32.ofInt(0);
while( true ) {
char = readChar();
switch( char ) {
case 48,49: // 0-1
n = haxe.Int32.add(haxe.Int32.shl(n,1), cast (char - 48));
case '_'.code:
default:
this.char = char;
// we allow to parse binary Int32 in Neko, but when the value will be
// evaluated by Interpreter, a failure will occur if no Int32 operation is
// performed
var v = try CInt(haxe.Int32.toInt(n)) catch( e : Dynamic ) CInt32(n);
return TConst(v);
}
}
#end
default: default:
this.char = char; this.char = char;
var i = Std.int(n); var i = Std.int(n);
@@ -1477,7 +1799,22 @@ class Parser {
case "[".code: return TBkOpen; case "[".code: return TBkOpen;
case "]".code: return TBkClose; case "]".code: return TBkClose;
case "'".code, '"'.code: return TConst( CString(readString(char)) ); case "'".code, '"'.code: return TConst( CString(readString(char)) );
case "?".code: return TQuestion; case "?".code:
char = readChar();
switch (char) {
case '?'.code:
var orp = readPos;
if (readChar() == '='.code)
return TOp("??=");
this.readPos = orp;
return TOp("??");
case '.'.code:
return TQuestionDot;
}
this.char = char;
return TQuestion;
case ":".code: return TDoubleDot; case ":".code: return TDoubleDot;
case '='.code: case '='.code:
char = readChar(); char = readChar();
@@ -1518,18 +1855,21 @@ class Parser {
default: default:
if( ops[char] ) { if( ops[char] ) {
var op = String.fromCharCode(char); var op = String.fromCharCode(char);
var prev = -1;
while( true ) { while( true ) {
char = readChar(); char = readChar();
if( StringTools.isEof(char) ) char = 0; if( StringTools.isEof(char) ) char = 0;
if( !ops[char] || prev == '='.code ) { if( !ops[char] ) {
if( op.charCodeAt(0) == '/'.code )
return tokenComment(op,char);
this.char = char; this.char = char;
return TOp(op); return TOp(op);
} }
prev = char; var pop = op;
op += String.fromCharCode(char); op += String.fromCharCode(char);
if( !opPriority.exists(op) && opPriority.exists(pop) ) {
if( op == "//" || op == "/*" )
return tokenComment(op,char);
this.char = char;
return TOp(pop);
}
} }
} }
if( idents[char] ) { if( idents[char] ) {
@@ -1564,6 +1904,21 @@ class Parser {
push(TPOpen); push(TPOpen);
parseExpr(); parseExpr();
case TId(id): case TId(id):
while(true) {
var tk = token();
if(tk == TDot) {
id += ".";
tk = token();
switch(tk) {
case TId(id2):
id += id2;
default: unexpected(tk);
}
} else {
push(tk);
break;
}
}
mk(EIdent(id), tokenMin, tokenMax); mk(EIdent(id), tokenMin, tokenMax);
case TOp("!"): case TOp("!"):
mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax); mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax);
@@ -1576,6 +1931,14 @@ class Parser {
switch( expr(e) ) { switch( expr(e) ) {
case EIdent(id): case EIdent(id):
return preprocValue(id) != null; return preprocValue(id) != null;
case EField(e2, f):
switch(expr(e2)) {
case EIdent(id):
return preprocValue(id + "." + f) != null;
default:
error(EInvalidPreprocessor("Can't eval " + expr(e).getName() + " with " + expr(e2).getName()), readPos, readPos);
return false;
}
case EUnop("!", _, e): case EUnop("!", _, e):
return !evalPreproCond(e); return !evalPreproCond(e);
case EParent(e): case EParent(e):
@@ -1629,6 +1992,7 @@ 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); error(EInvalidPreprocessor("Unclosed"), pos, pos);
if( preprocStack[spos] != obj ) { if( preprocStack[spos] != obj ) {
@@ -1702,6 +2066,7 @@ class Parser {
case TBrOpen: "{"; case TBrOpen: "{";
case TBrClose: "}"; case TBrClose: "}";
case TDot: "."; case TDot: ".";
case TQuestionDot: "?.";
case TComma: ","; case TComma: ",";
case TSemicolon: ";"; case TSemicolon: ";";
case TBkOpen: "["; case TBkOpen: "[";
+27 -6
View File
@@ -114,6 +114,25 @@ class Printer {
return; return;
} }
switch( #if hscriptPos e.e #else e #end ) { 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): case EConst(c):
switch( c ) { switch( c ) {
case CInt(i): add(i); case CInt(i): add(i);
@@ -122,7 +141,7 @@ class Printer {
} }
case EIdent(v): case EIdent(v):
add(v); add(v);
case EVar(n, t, e): case EVar(n, t, e): // TODO: static, public, override
add("var " + n); add("var " + n);
addType(t); addType(t);
if( e != null ) { if( e != null ) {
@@ -145,9 +164,9 @@ class Printer {
tabs = tabs.substr(1); tabs = tabs.substr(1);
add("}"); add("}");
} }
case EField(e, f): case EField(e, f, s):
expr(e); expr(e);
add("." + f); add((s == true ? "?." : ".") + f);
case EBinop(op, e1, e2): case EBinop(op, e1, e2):
expr(e1); expr(e1);
add(" " + op + " "); add(" " + op + " ");
@@ -207,7 +226,7 @@ class Printer {
add("break"); add("break");
case EContinue: case EContinue:
add("continue"); add("continue");
case EFunction(params, e, name, ret): case EFunction(params, e, name, ret): // TODO: static, public, override
add("function"); add("function");
if( name != null ) if( name != null )
add(" " + name); add(" " + name);
@@ -234,7 +253,7 @@ class Printer {
add("["); add("[");
expr(index); expr(index);
add("]"); add("]");
case EArrayDecl(el): case EArrayDecl(el, _):
add("["); add("[");
var first = true; var first = true;
for( e in el ) { for( e in el ) {
@@ -331,7 +350,7 @@ class Printer {
public static function errorToString( e : Expr.Error ) { public static function errorToString( e : Expr.Error ) {
var message = switch( #if hscriptPos e.e #else e #end ) { 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 EUnexpected(s): "Unexpected token: \""+s+"\"";
case EUnterminatedString: "Unterminated string"; case EUnterminatedString: "Unterminated string";
case EUnterminatedComment: "Unterminated comment"; case EUnterminatedComment: "Unterminated comment";
@@ -341,6 +360,8 @@ class Printer {
case EInvalidOp(op): "Invalid operator: "+op; case EInvalidOp(op): "Invalid operator: "+op;
case EInvalidAccess(f): "Invalid access to field " + f; case EInvalidAccess(f): "Invalid access to field " + f;
case ECustom(msg): msg; case ECustom(msg): msg;
case EInvalidClass(cla): "Invalid class: " + cla + " was not found.";
case EAlreadyExistingClass(cla): 'Custom Class named $cla already exists.';
}; };
#if hscriptPos #if hscriptPos
return e.origin + ":" + e.line + ": " + message; return e.origin + ":" + e.line + ": " + message;
+5
View File
@@ -27,6 +27,8 @@ class Tools {
public static function iter( e : Expr, f : Expr -> Void ) { public static function iter( e : Expr, f : Expr -> Void ) {
switch( expr(e) ) { switch( expr(e) ) {
case EConst(_), EIdent(_): 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 EVar(_, _, e): if( e != null ) f(e);
case EParent(e): f(e); case EParent(e): f(e);
case EBlock(el): for( e in el ) f(e); case EBlock(el): for( e in el ) f(e);
@@ -57,6 +59,7 @@ class Tools {
if( def != null ) f(def); if( def != null ) f(def);
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e); case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
case ECheckType(e,_): 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 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 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 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); return mk(edef, e);
} }
+308
View File
@@ -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