Compare commits

...
16 Commits
Author SHA1 Message Date
Nicolas Cannasse 09923651d8 2.1.0 2017-07-18 18:47:06 +02:00
Nicolas Cannasse 7ca5b85051 added optional metadata support in toplevel expr and anon types 2017-07-18 17:28:15 +02:00
Andy Li a34faf8a26 [TravisCI] use newer versions of osx and flashplayer 2017-06-27 17:24:01 +08:00
Andy Li 7708159e92 [TravisCI] haxe development tmp fix
https://github.com/HaxeFoundation/haxe/pull/6253#issuecomment-300717995
2017-05-14 00:11:15 +08:00
Andy Li 7851d48e82 [CI] test with Haxe 3.4.2 2017-05-13 23:30:51 +08:00
Andy Li f320b4fa9b [AppVeyor] fix php install 2017-05-11 09:54:17 +08:00
Andy Li b3ea81f4e8 [TravisCI] use Trusty 2017-05-11 09:38:27 +08:00
Nicolas Cannasse ace61e589d moved build scripts in /bin 2017-05-06 11:14:45 +02:00
Tom CoxonandNicolas Cannasse 51506e0400 Add filename / line number error reporting with -D hscriptPos (#57) 2017-01-02 17:48:48 +01:00
Andy Li 4a1432b01d [TravisCI] flash-player-debuger has been moved to caskroom/versions 2016-10-16 23:35:42 +08:00
Pavel AlexandrovandNicolas Cannasse aa16393c1b Add do ... while support. (#51)
Add `do ... while` support.
2016-10-03 12:24:53 +02:00
Andy Li 55ed2c0d5c Avoid using Array#sort in test.
There is some problem with the php target. Let's workaround it for now.
2016-10-01 15:14:58 +08:00
Andy Li 6c588733d9 [CI] updated flash player install 2016-10-01 12:14:25 +08:00
Andy LiandGitHub d72411632d [TravisCI] use OSX 10.10 2016-10-01 10:59:02 +08:00
romamikandNicolas Cannasse a1af1ec29e Added Map support (#49)
Map support
2016-09-28 13:04:18 +02:00
Andy Li bdd55483f9 add a line in release.bat to remind Nicolas to create a git tag 2016-08-21 22:33:13 +08:00
33 changed files with 487 additions and 159 deletions
+15 -17
View File
@@ -4,8 +4,12 @@ os:
- linux
- osx
sudo: false
dist: trusty
haxe:
- "3.2.1"
- "3.4.2"
- development
addons:
@@ -22,14 +26,8 @@ addons:
- mono-devel
- mono-mcs
# Flash
- libcurl3:i386
- libglib2.0-0:i386
- libx11-6:i386
- libxext6:i386
- libxt6:i386
- libxcursor1:i386
- libnss3:i386
- libgtk2.0-0:i386
- libglib2.0
- libfreetype6
install:
# os-specific config
@@ -62,12 +60,12 @@ script:
- pushd script &&
haxe build.hxml &&
popd
- haxe build-interp.hxml
- haxe build-neko.hxml && neko bin/Test.n
- haxe build-js.hxml && node bin/Test.js
- haxe build-java.hxml && java -jar bin/Test.jar
- haxe build-cs.hxml && mono bin/bin/Test.exe
- haxe build-cpp.hxml && ./bin/Test
- haxe build-flash.hxml -D fdb && haxe flash/run.hxml bin/Test.swf
- haxe build-php.hxml && php bin/index.php
- haxe build-python.hxml && python3 bin/Test.py
- haxe bin/build-interp.hxml
- haxe bin/build-neko.hxml && neko bin/Test.n
- haxe bin/build-js.hxml && node bin/Test.js
- haxe bin/build-java.hxml && java -jar bin/Test.jar
- haxe bin/build-cs.hxml && mono bin/bin/Test.exe
- haxe bin/build-cpp.hxml && ./bin/Test
- haxe bin/build-flash.hxml -D fdb && haxe flash/run.hxml bin/Test.swf
- haxe bin/build-php.hxml && php bin/index.php
- haxe bin/build-python.hxml && python3 bin/Test.py
+53
View File
@@ -1,3 +1,5 @@
import haxe.ds.EnumValueMap;
import haxe.ds.Option;
import hscript.Macro;
import haxe.unit.*;
@@ -73,6 +75,7 @@ class Test extends TestCase {
assertScript("(function(a,b) return a + b)(4,5)",9);
assertScript("var y = 0; var add = function(a) y += a; add(5); add(3); y", 8);
assertScript("var a = [1,[2,[3,[4,null]]]]; var t = 0; while( a != null ) { t += a[0]; a = a[1]; }; t",10);
assertScript("var a = false; do { a = true; } while (!a); a;",true);
assertScript("var t = 0; for( x in 1...10 ) t += x; t", 45);
#if haxe3
assertScript("var t = 0; for( x in new IntIterator(1,10) ) t +=x; t", 45);
@@ -94,6 +97,56 @@ class Test extends TestCase {
assertScript("/**/0", 0);
assertScript("x=1;x*=-2", -2);
}
function testMap():Void {
var objKey = { ok:true };
var vars = {
stringMap: ["foo" => "Foo", "bar" => "Bar"],
intMap:[100 => "one hundred"],
objKey: objKey,
objMap:[objKey => "ok"],
enumKey:Option.Some("some"),
enumMap:new EnumValueMap<Option<String>, String>(),
stringIntMap: ["foo" => 100]
}
vars.enumMap.set(vars.enumKey, "ok");
assertScript('stringMap["foo"]', "Foo", vars);
assertScript('intMap[100]', "one hundred", vars);
assertScript('objMap[objKey]', "ok", vars);
assertScript('enumMap[enumKey]', "ok", vars);
assertScript('stringMap["a"] = "A"; stringMap["a"]', "A", vars);
assertScript('intMap[200] = objMap[{foo:false}] = enumMap[enumKey] = "A"', "A", vars);
assertEquals('A', vars.intMap[200]);
assertEquals('A', vars.enumMap.get(vars.enumKey));
for (key in vars.objMap.keys()) {
if (key != objKey) {
assertEquals(false, (key:Dynamic).foo);
assertEquals('A', vars.objMap[key]);
}
}
assertScript('
var keys = [];
for (key in stringMap.keys()) keys.push(key);
keys.join("_");
', {
var keys = [];
for (key in vars.stringMap.keys()) keys.push(key);
keys.join("_");
}, vars);
assertScript('stringMap.remove("foo"); stringMap.exists("foo");', false, vars);
assertScript('stringMap["foo"] = "a"; stringMap["foo"] += "b"', 'ab', vars);
assertEquals('ab', vars.stringMap['foo']);
assertScript('stringIntMap["foo"]++', 100, vars);
assertEquals(101, vars.stringIntMap['foo']);
assertScript('++stringIntMap["foo"]', 102, vars);
assertScript('var newMap = ["foo"=>"foo"]; newMap["foo"];', 'foo', vars);
#if (!php || (haxe_ver >= 3.3))
assertScript('var newMap = [enumKey=>"foo"]; newMap[enumKey];', 'foo', vars);
#end
assertScript('var newMap = [{a:"a"}=>"foo", objKey=>"bar"]; newMap[objKey];', 'bar', vars);
}
static function main() {
var runner = new TestRunner();
+12 -10
View File
@@ -6,13 +6,15 @@ environment:
install:
# Install the haxe chocolatey package (https://chocolatey.org/packages/haxe)
- cinst haxe -version 3.2.1 -y
- cinst haxe -version 3.4.2 -y
- RefreshEnv
# Setup haxelib
- mkdir "%HAXELIB_ROOT%"
- haxelib setup "%HAXELIB_ROOT%"
# Install test dependencies
- ps: Set-Service wuauserv -StartupType Manual
- cinst php -y
- RefreshEnv
# Download and setup a standalone flash player debugger
- haxe flash/install.hxml
# Install project dependencies
@@ -28,12 +30,12 @@ test_script:
- pushd script &&
haxe build.hxml &&
popd
- haxe build-interp.hxml
- haxe build-neko.hxml && neko bin\Test.n
- haxe build-js.hxml && node bin\Test.js
- haxe build-java.hxml && java -jar bin\Test.jar
- haxe build-cs.hxml && bin\bin\Test.exe
- haxe build-cpp.hxml && bin\Test.exe
- haxe build-flash.hxml -D fdb && haxe flash\run.hxml bin\Test.swf
- haxe build-php.hxml && C:\tools\php\php.exe bin\index.php
- haxe build-python.hxml && C:\Python34-x64\python.exe bin\Test.py
- haxe bin/build-interp.hxml
- haxe bin/build-neko.hxml && neko bin\Test.n
- haxe bin/build-js.hxml && node bin\Test.js
- haxe bin/build-java.hxml && java -jar bin\Test.jar
- haxe bin/build-cs.hxml && bin\bin\Test.exe
- haxe bin/build-cpp.hxml && bin\Test.exe
- haxe bin/build-flash.hxml -D fdb && haxe flash\run.hxml bin\Test.swf
- haxe bin/build-php.hxml && php bin\index.php
- haxe bin/build-python.hxml && C:\Python34-x64\python.exe bin\Test.py
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-cpp bin
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-cs bin
+1 -1
View File
@@ -1,4 +1,4 @@
build-each.hxml
bin/build-each.hxml
-swf bin/Test.swf
-swf-header 800:600:30:FFFFFF
--flash-strict
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
--interp
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-java bin
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-js bin/Test.js
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-neko bin/Test.n
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-php bin
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-python bin/Test.py
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-cpp bin
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-cs bin
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
--interp
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-java bin
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-js bin/Test.js
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-neko bin/Test.n
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-php bin
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-python bin/Test.py
+24 -7
View File
@@ -1,5 +1,4 @@
import Sys.*;
import sys.FileSystem.*;
import sys.io.File.*;
import haxe.*;
import haxe.io.*;
@@ -8,11 +7,11 @@ class Install {
// https://www.adobe.com/support/flashplayer/downloads.html
static var fpDownload(default, never) = switch (systemName()) {
case "Linux":
"https://fpdownload.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.i386.tar.gz";
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flash_player_sa_linux_debug.x86_64.tar.gz";
case "Mac":
"https://fpdownload.macromedia.com/pub/flashplayer/updaters/19/flashplayer_19_sa_debug.dmg";
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flashplayer_25_sa_debug.dmg";
case "Windows":
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/19/flashplayer_19_sa_debug.exe";
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flashplayer_25_sa_debug.exe";
case _:
throw "unsupported system";
}
@@ -47,9 +46,12 @@ class Install {
if (command("tar", ["-xf", Path.withoutDirectory(fpDownload), "-C", "flash"]) != 0)
throw "failed to extract flash player";
case "Mac":
if (command("brew", ["install", "caskroom/cask/brew-cask"]) != 0)
throw "failed to brew install caskroom/cask/brew-cask";
if (command("brew", ["cask", "install", "flash-player-debugger", "--appdir=flash"]) != 0)
// https://github.com/caskroom/homebrew-cask/pull/15381
if (command("brew", ["uninstall", "--force", "brew-cask"]) != 0)
throw "failed to brew uninstall --force brew-cask";
if (command("brew", ["tap", "caskroom/versions"]) != 0)
throw "failed to brew tap caskroom/versions";
if (command("brew", ["cask", "install", "flash-player-debugger"]) != 0)
throw "failed to install flash-player-debugger";
case "Windows":
// Download flash player
@@ -74,4 +76,19 @@ class Install {
};
http.customRequest(false, write(saveAs));
}
static function createDirectory(dir:String):Void {
try {
sys.FileSystem.createDirectory(dir);
} catch(e:Dynamic) {
switch (systemName()) {
case "Mac", "Linux":
if (command("sudo", ["mkdir", "-p", dir]) != 0)
throw 'cannot create $dir';
if (command("sudo", ["chmod", "a+rw", dir]) != 0)
throw 'cannot set permission of $dir';
case _:
throw 'cannot create $dir: $e';
}
}
}
}
+17 -5
View File
@@ -21,22 +21,34 @@ class Run {
var exitCode = switch (systemName()) {
case "Linux":
// The flash player has some issues with unexplained crashes,
// but if it runs about 8 times, it should succeed one of those...
// but if it runs about 16 times, it should succeed one of those...
var c = -1;
for (i in 0...8) {
if ((c = command("xvfb-run", ["flash/flashplayerdebugger", swf])) == 0)
for (i in 0...16) {
if ((c = command("xvfb-run", ["-a", "flash/flashplayerdebugger", swf])) == 0)
break;
println('retry... (${i+1})');
sleep(1.5);
}
c;
case "Mac":
command("flash/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger", [fullPath(swf)]);
command("/Applications/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger", [fullPath(swf)]);
case "Windows":
command("flash\\flashplayer.exe", [fullPath(swf)]);
case _:
throw "unsupported platform";
}
println(getContent(flashlog));
if (exists(flashlog))
println(getContent(flashlog));
else {
println('does not exist: $flashlog');
var parts = Path.normalize(flashlog).split("/");
println(parts);
for (i in 0...parts.length-1) {
var path = parts.splice(0, i+1).join("/");
println('ls $path');
command("ls", [path]);
}
}
exit(exitCode);
}
}
+2 -2
View File
@@ -3,7 +3,7 @@
"url": "https://github.com/HaxeFoundation/hscript",
"license": "MIT",
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
"version": "2.0.7",
"releasenote": "fixes for haxe 3.3, use property access by default",
"version": "2.1.0",
"releasenote": "added metadata support",
"contributors": ["ncannasse"]
}
+1 -1
View File
@@ -1 +1 @@
build-flash.hxml
bin/build-flash.hxml
+27 -8
View File
@@ -74,6 +74,13 @@ class Bytes {
return strings[id];
}
function doEncodeInt(v: Int) {
bout.addByte(v & 0xFF);
bout.addByte((v >> 8) & 0xFF);
bout.addByte((v >> 16) & 0xFF);
bout.addByte(v >>> 24);
}
function doEncodeConst( c : Const ) {
switch( c ) {
case CInt(v):
@@ -82,10 +89,7 @@ class Bytes {
bout.addByte(v);
} else {
bout.addByte(1);
bout.addByte(v & 0xFF);
bout.addByte((v >> 8) & 0xFF);
bout.addByte((v >> 16) & 0xFF);
bout.addByte(v >>> 24);
doEncodeInt(v);
}
#if !haxe3
case CInt32(v):
@@ -105,13 +109,18 @@ class Bytes {
}
}
function doDecodeInt() {
var i = bin.get(pin) | (bin.get(pin+1) << 8) | (bin.get(pin+2) << 16) | (bin.get(pin+3) << 24);
pin += 4;
return i;
}
function doDecodeConst() {
return switch( bin.get(pin++) ) {
case 0:
CInt(bin.get(pin++));
case 1:
var i = bin.get(pin) | (bin.get(pin+1) << 8) | (bin.get(pin+2) << 16) | (bin.get(pin+3) << 24);
pin += 4;
var i = doDecodeInt();
CInt(i);
case 2:
CFloat( Std.parseFloat(doDecodeString()) );
@@ -131,6 +140,8 @@ class Bytes {
function doEncode( e : Expr ) {
#if hscriptPos
doEncodeString(e.origin);
doEncodeInt(e.line);
var e = e.e;
#end
bout.addByte(Type.enumIndex(e));
@@ -177,6 +188,9 @@ class Bytes {
case EWhile(cond,e):
doEncode(cond);
doEncode(e);
case EDoWhile(cond,e):
doEncode(cond);
doEncode(e);
case EFor(v,it,e):
doEncodeString(v);
doEncode(it);
@@ -238,7 +252,9 @@ class Bytes {
function doDecode() : Expr {
#if hscriptPos
return { e : _doDecode(), pmin : 0, pmax : 0 };
var origin = doDecodeString();
var line = doDecodeInt();
return { e : _doDecode(), pmin : 0, pmax : 0, origin : origin, line : line };
}
function _doDecode() : ExprDef {
#end
@@ -347,6 +363,9 @@ class Bytes {
}
var def = doDecode();
ESwitch(e, cases, def);
case 24:
var cond = doDecode();
EDoWhile(cond,doDecode());
case 255:
null;
default:
@@ -365,4 +384,4 @@ class Bytes {
return b.doDecode();
}
}
}
+46 -2
View File
@@ -38,6 +38,8 @@ typedef Expr = {
var e : ExprDef;
var pmin : Int;
var pmax : Int;
var origin : String;
var line : Int;
}
enum ExprDef {
#else
@@ -67,14 +69,18 @@ enum 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);
EDoWhile( cond : Expr, e : Expr);
EMeta( name : String, args : Array<Expr>, e : Expr );
}
typedef Argument = { name : String, ?t : CType, ?opt : Bool };
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
enum CType {
CTPath( path : Array<String>, ?params : Array<CType> );
CTFun( args : Array<CType>, ret : CType );
CTAnon( fields : Array<{ name : String, t : CType }> );
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
CTParent( t : CType );
}
@@ -83,10 +89,48 @@ class Error {
public var e : ErrorDef;
public var pmin : Int;
public var pmax : Int;
public function new(e, pmin, pmax) {
public var origin : String;
public var line : Int;
public function new(e, pmin, pmax, origin, line) {
this.e = e;
this.pmin = pmin;
this.pmax = pmax;
this.origin = origin;
this.line = line;
}
private function errorDefToString(): String {
switch (e) {
case EInvalidChar(c):
return "Invalid character: '"+String.fromCharCode(c)+"' ("+c+")";
case EUnexpected(s):
return "Unexpected token: \""+s+"\"";
case EUnterminatedString:
return "Unterminated string";
case EUnterminatedComment:
return "Unterminated comment";
case EUnknownVariable(v):
return "Unknown variable: "+v;
case EInvalidIterator(v):
return "Invalid iterator: "+v;
case EInvalidOp(op):
return "Invalid operator: "+op;
case EInvalidAccess(f):
return "Invalid access to field "+f;
}
}
public function toString(): String {
var message = errorDefToString();
message = origin + ":" + line + ": " + message;
return message;
}
}
enum ErrorDef {
+153 -37
View File
@@ -23,6 +23,7 @@
* DAMAGE.
*/
package hscript;
import haxe.PosInfos;
import hscript.Expr;
private enum Stop {
@@ -63,10 +64,18 @@ class Interp {
variables.set("null",null);
variables.set("true",true);
variables.set("false",false);
variables.set("trace",function(e) haxe.Log.trace(Std.string(e),cast { fileName : "hscript", lineNumber : 0 }));
variables.set("trace",function(e) haxe.Log.trace(Std.string(e), posInfos()));
initOps();
}
public function posInfos(): PosInfos {
#if hscriptPos
if (curExpr != null)
return cast { fileName : curExpr.origin, lineNumber : curExpr.line };
#end
return cast { fileName : "hscript", lineNumber : 0 };
}
function initOps() {
var me = this;
#if haxe3
@@ -119,8 +128,16 @@ class Interp {
l.r = v;
case EField(e,f):
v = set(expr(e),f,v);
case EArray(e,index):
expr(e)[expr(index)] = v;
case EArray(e, index):
var arr:Dynamic = expr(e);
var index:Dynamic = expr(index);
if (isMap(arr)) {
setMapValue(arr, index, v);
}
else {
arr[index] = v;
}
default:
error(EInvalidOp("="));
}
@@ -146,11 +163,17 @@ class Interp {
var obj = expr(e);
v = fop(get(obj,f),expr(e2));
v = set(obj,f,v);
case EArray(e,index):
var arr = expr(e);
var index = expr(index);
v = fop(arr[index],expr(e2));
arr[index] = v;
case EArray(e, index):
var arr:Dynamic = expr(e);
var index:Dynamic = expr(index);
if (isMap(arr)) {
v = fop(getMapValue(arr, index), expr(e2));
setMapValue(arr, index, v);
}
else {
v = fop(arr[index],expr(e2));
arr[index] = v;
}
default:
return error(EInvalidOp(op));
}
@@ -181,16 +204,29 @@ class Interp {
} else
set(obj,f,v + delta);
return v;
case EArray(e,index):
var arr = expr(e);
var index = expr(index);
var v = arr[index];
if( prefix ) {
v += delta;
arr[index] = v;
} else
arr[index] = v + delta;
return v;
case EArray(e, index):
var arr:Dynamic = expr(e);
var index:Dynamic = expr(index);
if (isMap(arr)) {
var v = getMapValue(arr, index);
if (prefix) {
v += delta;
setMapValue(arr, index, v);
}
else {
setMapValue(arr, index, v + delta);
}
return v;
}
else {
var v = arr[index];
if( prefix ) {
v += delta;
arr[index] = v;
} else
arr[index] = v + delta;
return v;
}
default:
return error(EInvalidOp((delta > 0)?"++":"--"));
}
@@ -248,7 +284,7 @@ class Interp {
inline function error(e : #if hscriptPos ErrorDef #else Error #end ) : Dynamic {
#if hscriptPos
throw new Error(e, curExpr.pmin, curExpr.pmax);
throw new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line);
#else
throw e;
#end
@@ -338,6 +374,9 @@ class Interp {
case EWhile(econd,e):
whileLoop(econd,e);
return null;
case EDoWhile(econd,e):
doWhileLoop(econd,e);
return null;
case EFor(v,it,e):
forLoop(v,it,e);
return null;
@@ -417,12 +456,56 @@ class Interp {
}
return f;
case EArrayDecl(arr):
var a = new Array();
for( e in arr )
a.push(expr(e));
return a;
case EArray(e,index):
return expr(e)[expr(index)];
if (arr.length > 0 && edef(arr[0]).match(EBinop("=>", _))) {
var isAllString:Bool = true;
var isAllInt:Bool = true;
var isAllObject:Bool = true;
var isAllEnum:Bool = true;
var keys:Array<Dynamic> = [];
var values:Array<Dynamic> = [];
for (e in arr) {
switch(edef(e)) {
case EBinop("=>", eKey, eValue): {
var key:Dynamic = expr(eKey);
var value:Dynamic = expr(eValue);
isAllString = isAllString && Std.is(key, String);
isAllInt = isAllInt && Std.is(key, Int);
isAllObject = isAllObject && Reflect.isObject(key);
isAllEnum = isAllEnum && Reflect.isEnumValue(key);
keys.push(key);
values.push(value);
}
default: throw("=> expected");
}
}
var map:Dynamic = {
if (isAllInt) new haxe.ds.IntMap<Dynamic>();
else if (isAllString) new haxe.ds.StringMap<Dynamic>();
else if (isAllEnum) new haxe.ds.EnumValueMap<Dynamic, Dynamic>();
else if (isAllObject) new haxe.ds.ObjectMap<Dynamic, Dynamic>();
else throw 'Inconsistent key types';
}
for (n in 0...keys.length) {
setMapValue(map, keys[n], values[n]);
}
return map;
}
else {
var a = new Array();
for ( e in arr ) {
a.push(expr(e));
}
return a;
}
case EArray(e, index):
var arr:Dynamic = expr(e);
var index:Dynamic = expr(index);
if (isMap(arr)) {
return getMapValue(arr, index);
}
else {
return arr[index];
}
case ENew(cl,params):
var a = new Array();
for( e in params )
@@ -477,10 +560,29 @@ class Interp {
if( !match )
val = def == null ? null : expr(def);
return val;
case EMeta(_, _, e):
return expr(e);
}
return null;
}
function doWhileLoop(econd,e) {
var old = declared.length;
do {
try {
expr(e);
} catch( err : Stop ) {
switch(err) {
case SContinue:
case SBreak: break;
case SReturn(_): throw err;
}
}
}
while( expr(econd) == true );
restore(old);
}
function whileLoop(econd,e) {
var old = declared.length;
while( expr(econd) == true ) {
@@ -498,8 +600,8 @@ class Interp {
}
function makeIterator( v : Dynamic ) : Iterator<Dynamic> {
#if (flash && !flash9)
if( v.iterator != null ) v = v.iterator();
#if ((flash && !flash9) || php)
if ( v.iterator != null ) v = v.iterator();
#else
try v = v.iterator() catch( e : Dynamic ) {};
#end
@@ -526,18 +628,32 @@ class Interp {
restore(old);
}
inline function isMap(o:Dynamic):Bool {
return Std.is(o, haxe.Constraints.IMap);
}
inline function getMapValue(map:Dynamic, key:Dynamic):Dynamic {
return cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).get(key);
}
inline function setMapValue(map:Dynamic, key:Dynamic, value:Dynamic):Void {
cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).set(key, value);
}
function get( o : Dynamic, f : String ) : Dynamic {
if( o == null ) error(EInvalidAccess(f));
#if php
// https://github.com/HaxeFoundation/haxe/issues/4915
return try {
if ( o == null ) error(EInvalidAccess(f));
return {
#if php
// https://github.com/HaxeFoundation/haxe/issues/4915
try {
Reflect.getProperty(o, f);
} catch (e:Dynamic) {
Reflect.field(o, f);
}
#else
Reflect.getProperty(o, f);
} catch (e:Dynamic) {
Reflect.field(o, f);
}
#else
return Reflect.getProperty(o, f);
#end
#end
}
}
function set( o : Dynamic, f : String, v : Dynamic ) : Dynamic {
+6 -1
View File
@@ -180,6 +180,8 @@ class Macro {
EIf(convert(c), convert(e1), e2 == null ? null : convert(e2));
case EWhile(c, e):
EWhile(convert(c), convert(e), true);
case EDoWhile(c, e):
EWhile(convert(c), convert(e), false);
#if (haxe_211 || haxe3)
case EFor(v, it, efor):
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
@@ -229,7 +231,10 @@ class Macro {
ETernary(convert(cond), convert(e1), convert(e2));
case ESwitch(e, cases, edef):
ESwitch(convert(e), [for( c in cases ) { values : [for( v in c.values ) convert(v)], expr : convert(c.expr) } ], edef == null ? null : convert(edef));
case EMeta(m, params, esub):
var mpos = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EMeta({ name : m, params : params == null ? [] : [for( p in params ) convert(p)], pos : mpos }, convert(esub));
}, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end }
}
}
}
+105 -52
View File
@@ -41,6 +41,7 @@ enum Token {
TBkClose;
TQuestion;
TDoubleDot;
TMeta( s : String );
}
class Parser {
@@ -69,6 +70,11 @@ class Parser {
**/
public var allowTypes : Bool;
/**
allow haxe metadata declarations
**/
public var allowMetadata : Bool;
// implementation
var input : haxe.io.Input;
var char : Int;
@@ -77,6 +83,7 @@ class Parser {
var uid : Int = 0;
#if hscriptPos
var origin : String;
var readPos : Int;
var tokenMin : Int;
var tokenMax : Int;
@@ -111,7 +118,7 @@ class Parser {
["..."],
["&&"],
["||"],
["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^="],
["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^=","=>"],
];
#if haxe3
opPriority = new Map();
@@ -133,7 +140,7 @@ class Parser {
public inline function error( err, pmin, pmax ) {
#if hscriptPos
throw new Error(err, pmin, pmax);
throw new Error(err, pmin, pmax, origin, line);
#else
throw err;
#end
@@ -143,14 +150,15 @@ class Parser {
error(EInvalidChar(c), readPos, readPos);
}
public function parseString( s : String ) {
line = 1;
public function parseString( s : String, ?origin : String = "hscript" ) {
uid = 0;
return parse( new haxe.io.StringInput(s) );
return parse( new haxe.io.StringInput(s), origin );
}
public function parse( s : haxe.io.Input ) {
public function parse( s : haxe.io.Input, ?origin : String = "hscript" ) {
line = 1;
#if hscriptPos
this.origin = origin;
readPos = 0;
tokenMin = oldTokenMin = 0;
tokenMax = oldTokenMax = 0;
@@ -198,6 +206,16 @@ class Parser {
if( t != tk ) unexpected(t);
}
function getIdent() {
var tk = token();
switch( tk ) {
case TId(id): return id;
default:
unexpected(tk);
return null;
}
}
inline function expr(e:Expr) {
#if hscriptPos
return e.e;
@@ -224,9 +242,10 @@ class Parser {
inline function mk(e,?pmin,?pmax) : Expr {
#if hscriptPos
if( e == null ) return null;
if( pmin == null ) pmin = tokenMin;
if( pmax == null ) pmax = tokenMax;
return { e : e, pmin : pmin, pmax : pmax };
return { e : e, pmin : pmin, pmax : pmax, origin : origin, line : line };
#else
return e;
#end
@@ -241,6 +260,7 @@ class Parser {
case EBinop(_,_,e): isBlock(e);
case EUnop(_,prefix,e): !prefix && isBlock(e);
case EWhile(_,e): isBlock(e);
case EDoWhile(_,e): isBlock(e);
case EFor(_,_,e): isBlock(e);
case EReturn(e): e != null && isBlock(e);
case ETry(_, _, _, e): isBlock(e);
@@ -370,7 +390,7 @@ class Parser {
}
if( a.length == 1 )
switch( expr(a[0]) ) {
case EFor(_), EWhile(_):
case EFor(_), EWhile(_), EDoWhile(_):
var tmp = "__a_" + (uid++);
var e = mk(EBlock([
mk(EVar(tmp, null, mk(EArrayDecl([]), p1)), p1),
@@ -380,18 +400,47 @@ class Parser {
return parseExprNext(e);
default:
}
return parseExprNext(mk(EArrayDecl(a),p1));
return parseExprNext(mk(EArrayDecl(a), p1));
case TMeta(id) if( allowMetadata ):
var args = parseMetaArgs();
return mk(EMeta(id, args, parseExpr()),p1);
default:
return unexpected(tk);
}
}
function parseMetaArgs() {
var tk = token();
if( tk != TPOpen ) {
push(tk);
return null;
}
var args = [];
tk = token();
if( tk != TPClose ) {
push(tk);
while( true ) {
args.push(parseExpr());
switch( token() ) {
case TComma:
case TPClose:
break;
case tk:
unexpected(tk);
}
}
}
return args;
}
function mapCompr( tmp : String, e : Expr ) {
var edef = switch( expr(e) ) {
case EFor(v, it, e2):
EFor(v, it, mapCompr(tmp, e2));
case EWhile(cond, e2):
EWhile(cond, mapCompr(tmp, e2));
case EDoWhile(cond, e2):
EDoWhile(cond, mapCompr(tmp, e2));
case EIf(cond, e1, e2) if( e2 == null ):
EIf(cond, mapCompr(tmp, e1), null);
case EBlock([e]):
@@ -454,13 +503,8 @@ class Parser {
}
mk(EIf(cond,e1,e2),p1,(e2 == null) ? tokenMax : pmax(e2));
case "var":
var ident = getIdent();
var tk = token();
var ident = null;
switch(tk) {
case TId(id): ident = id;
default: unexpected(tk);
}
tk = token();
var t = null;
if( tk == TDoubleDot && allowTypes ) {
t = parseType();
@@ -476,15 +520,20 @@ class Parser {
var econd = parseExpr();
var e = parseExpr();
mk(EWhile(econd,e),p1,pmax(e));
case "do":
var e = parseExpr();
var tk = token();
switch(tk)
{
case TId("while"): // Valid
default: unexpected(tk);
}
var econd = parseExpr();
mk(EDoWhile(econd,e),p1,pmax(econd));
case "for":
ensure(TPOpen);
var vname = getIdent();
var tk = token();
var vname = null;
switch( tk ) {
case TId(id): vname = id;
default: unexpected(tk);
}
tk = token();
if( !Type.enumEq(tk,TId("in")) ) unexpected(tk);
var eiter = parseExpr();
ensure(TPClose);
@@ -552,21 +601,13 @@ class Parser {
mk(EReturn(e),p1,if( e == null ) tokenMax else pmax(e));
case "new":
var a = new Array();
var tk = token();
switch( tk ) {
case TId(id): a.push(id);
default: unexpected(tk);
}
a.push(getIdent());
var next = true;
while( next ) {
tk = token();
var tk = token();
switch( tk ) {
case TDot:
tk = token();
switch(tk) {
case TId(id): a.push(id);
default: unexpected(tk);
}
a.push(getIdent());
case TPOpen:
next = false;
default:
@@ -583,11 +624,7 @@ class Parser {
var tk = token();
if( !Type.enumEq(tk, TId("catch")) ) unexpected(tk);
ensure(TPOpen);
tk = token();
var vname = switch( tk ) {
case TId(id): id;
default: unexpected(tk);
}
var vname = getIdent();
ensure(TDoubleDot);
var t = null;
if( allowTypes )
@@ -684,12 +721,7 @@ class Parser {
}
return makeBinop(op,e1,parseExpr());
case TDot:
tk = token();
var field = null;
switch(tk) {
case TId(id): field = id;
default: unexpected(tk);
}
var field = getIdent();
return parseExprNext(mk(EField(e1,field),pmin(e1)));
case TPOpen:
return parseExprNext(mk(ECall(e1,parseExprList(TPClose)),pmin(e1)));
@@ -717,13 +749,7 @@ class Parser {
t = token();
if( t != TDot )
break;
t = token();
switch( t ) {
case TId(v):
path.push(v);
default:
unexpected(t);
}
path.push(getIdent());
}
var params = null;
switch( t ) {
@@ -742,7 +768,7 @@ class Parser {
tokens.add({ t : TOp(op.substr(1)), min : tokenMax - op.length - 1, max : tokenMax });
#else
tokens.add(TOp(op.substr(1)));
#end
#end
break;
}
default:
@@ -761,19 +787,29 @@ class Parser {
return parseTypeNext(CTParent(t));
case TBrOpen:
var fields = [];
var meta = null;
while( true ) {
t = token();
switch( t ) {
case TBrClose: break;
case TId("var"):
var name = getIdent();
ensure(TDoubleDot);
fields.push( { name : name, t : parseType(), meta : meta } );
meta = null;
ensure(TSemicolon);
case TId(name):
ensure(TDoubleDot);
fields.push( { name : name, t : parseType() } );
fields.push( { name : name, t : parseType(), meta : meta } );
t = token();
switch( t ) {
case TComma:
case TBrClose: break;
default: unexpected(t);
}
case TMeta(name):
if( meta == null ) meta = [];
meta.push({ name : name, params : parseMetaArgs() });
default:
unexpected(t);
}
@@ -1062,8 +1098,24 @@ class Parser {
char = readChar();
if( char == '='.code )
return TOp("==");
else if ( char == '>'.code )
return TOp("=>");
this.char = char;
return TOp("=");
case '@'.code:
char = readChar();
if( idents[char] || char == ':'.code ) {
var id = String.fromCharCode(char);
while( true ) {
char = readChar();
if( !idents[char] ) {
this.char = char;
return TMeta(id);
}
id += String.fromCharCode(char);
}
}
invalidChar(char);
default:
if( ops[char] ) {
var op = String.fromCharCode(char);
@@ -1168,6 +1220,7 @@ class Parser {
case TBkClose: "]";
case TQuestion: "?";
case TDoubleDot: ":";
case TMeta(id): "@" + id;
}
}
+6
View File
@@ -148,6 +148,12 @@ class Printer {
expr(cond);
add(" ) ");
expr(e);
case EDoWhile(cond,e):
add("do ");
expr(e);
add(" while ( ");
expr(cond);
add(" )");
case EFor(v, it, e):
add("for( "+v+" in ");
expr(it);
+2
View File
@@ -15,6 +15,7 @@ class Tools {
case ECall(e, args): f(e); for( a in args ) f(a);
case EIf(c, e1, e2): f(c); f(e1); if( e2 != null ) f(e2);
case EWhile(c, e): f(c); f(e);
case EDoWhile(c, e): f(c); f(e);
case EFor(_, it, e): f(it); f(e);
case EBreak,EContinue:
case EFunction(_, e, _, _): f(e);
@@ -48,6 +49,7 @@ class Tools {
case ECall(e, args): ECall(f(e),[for( a in args ) f(a)]);
case EIf(c, e1, e2): EIf(f(c),f(e1),if( e2 != null ) f(e2) else null);
case EWhile(c, e): EWhile(f(c),f(e));
case EDoWhile(c, e): EDoWhile(f(c),f(e));
case EFor(v, it, e): EFor(v, f(it), f(e));
case EBreak, EContinue: e;
case EFunction(args, e, name, t): EFunction(args, f(e), name, t);
+1
View File
@@ -15,4 +15,5 @@ haxe -xml release/haxedoc.xml hscript.Interp hscript.Parser hscript.Bytes hscrip
7z a -tzip release.zip release
rm -rf release
haxelib submit release.zip
echo Remember to "git tag vX.Y.Z && git push --tags"
pause