Compare commits

..
59 Commits
Author SHA1 Message Date
Nicolas Cannasse 70b11ec7ad 2.2.0 2018-04-14 12:23:12 +02:00
ncannasse f2944e0bae added rethrow() 2018-03-02 17:26:12 +01:00
ncannasse fdec33d086 support async transform with -D hscriptPos 2018-03-02 17:25:43 +01:00
ncannasse 0702074469 added ECustom error message 2018-03-02 17:22:35 +01:00
ncannasse 6d5cbf6974 correctly handle "return" in sync parts 2018-03-02 11:25:53 +01:00
Nicolas Cannasse 5429a3a4d4 added typeToString() 2018-02-04 22:50:28 +01:00
Nicolas Cannasse c124076279 added typedef parsing support 2018-02-04 20:54:08 +01:00
Nicolas Cannasse 0d1d811d2c use error instead of throw 2018-02-04 12:31:36 +01:00
ncannasse 8c04831339 don't pass return value in SReturn : big problem in JS that does a Std.string on exception value 2017-11-24 12:43:39 +01:00
ncannasse 4a8b2690aa fixed trace() with multiple arguments 2017-11-23 16:14:59 +01:00
ncannasse e2bc716ea7 fix 2017-11-23 15:05:04 +01:00
ncannasse 6c5987f9af fixed error when no inline triggered 2017-11-23 14:05:12 +01:00
ncannasse 1e79880c72 more conformance to haxe syntax wrt mandatory ;
added static and macro accessors
2017-11-23 12:40:50 +01:00
ncannasse f62d891c63 reduce OpNeg(CInt/CFloat) to negative Int/Float like haxe parser does 2017-11-23 12:17:23 +01:00
ncannasse 930cb8853c don't reset line + preprocessor fix 2017-11-23 11:34:44 +01:00
ncannasse 22104ff64e fixed preprocessor bug 2017-11-22 18:41:32 +01:00
ncannasse 17564441b5 added #if/#else support
added function arg default value expr (only if allowTypes, not supported by interp)
allowed local "inline function"
added parseModule
added exponent support in floats (1.5e-3)
2017-11-22 17:30:16 +01:00
ncannasse a9140a4403 bugfix haxe 4 2017-11-21 17:16:30 +01:00
ncannasse ce47ca0a8a fixed break & continue in sync-optimized expression 2017-11-21 15:55:38 +01:00
Alexander KuzmenkoandNicolas Cannasse 852fee170e [php] don't expect iterator to have iterator field (fixes #69) (#71)
* [php] don't expect IntIterator to have a field which does not exist (fixes #69)

* cleanup

* fix Interp.makeIterator for Haxe 3.4
2017-10-03 09:46:14 +02:00
Simon Krajewski 8463e99d13 tap that 2017-10-01 12:32:16 +02:00
Simon Krajewski 3c016b73ee semicolon 2017-10-01 12:24:41 +02:00
Simon Krajewski 8d4173b0be use php7 2017-10-01 12:22:08 +02:00
Simon Krajewski 502f043804 actually install hx3compat on the CI 2017-10-01 11:51:08 +02:00
Simon Krajewski f8571fb175 use hx3compat for haxe.unit for now 2017-10-01 11:47:58 +02:00
Nicolas Cannasse 7209aa8880 fixed @async in @sync, added scriptCall special API 2017-08-18 16:44:32 +02:00
Andy Li 1a4a1217ae haxe 3.2.1 compatibility 2017-08-17 10:35:30 +08:00
Nicolas Cannasse 139c360feb fixed parsing of @meta {} 2017-08-11 16:13:44 +02:00
Nicolas Cannasse be1afbdb5c fixes 2017-08-11 12:03:44 +02:00
Nicolas Cannasse 8a7e8c8d7d changed @async and @split 2017-08-11 12:03:35 +02:00
Nicolas Cannasse 931f79dacb move error formating to Printer 2017-08-11 11:03:29 +02:00
Nicolas Cannasse 261e6ee78e bug fixes 2017-08-11 11:03:06 +02:00
Nicolas Cannasse 9eaddcdafb license changed to MIT (close #67) 2017-08-10 16:56:31 +02:00
Nicolas Cannasse b8ede1a3e7 make sure Test include all other files to error when ast changes 2017-08-10 16:31:37 +02:00
Nicolas Cannasse bbaacd5d28 added Async 2017-08-10 16:31:10 +02:00
Nicolas Cannasse 60ed5fdfe2 added missing EMeta 2017-08-10 16:04:55 +02:00
Nicolas Cannasse 512f88c63e added EMeta support 2017-08-10 15:12:59 +02:00
Nicolas Cannasse 50c01b2cfb haxe 4 fixes 2017-08-10 15:05:38 +02:00
Nicolas Cannasse 27d3f889b5 fixed missing meta in TAnonymous 2017-07-20 11:39:24 +02:00
Nicolas Cannasse 140a9918c0 2.1.1 2017-07-19 22:14:41 +02:00
Nicolas CannasseandGitHub fc6a30b684 Update README.md 2017-07-19 21:22:33 +02:00
Nicolas CannasseandGitHub deb0ae8b8e Update README.md 2017-07-19 21:22:06 +02:00
Nicolas Cannasse 1425479569 fixed missing EMeta support 2017-07-19 21:19:20 +02:00
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
36 changed files with 1750 additions and 377 deletions
+19 -19
View File
@@ -4,8 +4,12 @@ os:
- linux
- osx
sudo: false
dist: trusty
haxe:
- "3.2.1"
- "3.4.2"
- development
addons:
@@ -16,30 +20,25 @@ addons:
- g++-multilib
# Python
- python3
# PHP
- php5-cli
# C#
- 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
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
export DISPLAY=:99.0;
export AUDIODEV=null;
phpenv global 7.0;
elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then
brew update;
brew install mono;
brew install python3;
brew tap homebrew/homebrew-php;
brew install php71;
fi
# Download and setup a standalone flash player debugger
- haxe flash/install.hxml
@@ -55,6 +54,7 @@ install:
fi
- haxelib install hxjava
- haxelib install hxcs
- haxelib install hx3compat
- haxelib dev hscript .
- haxelib list
@@ -62,12 +62,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
+22
View File
@@ -0,0 +1,22 @@
The MIT License
Copyright (C)2008-2017 Haxe Foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+2
View File
@@ -64,6 +64,8 @@ You can use `parser.allowJSON` to allow JSON data.
You can use `parser.allowTypes` to parse types for local vars, exceptions, function args and return types. Types are ignored by the interpreter.
You can use `parser.allowMetadata` to parse metadata before expressions on in anonymous types. Metadata are ignored by the interpreter.
You can use `new hscript.Macro(pos).convert(ast)` to convert an hscript AST to a Haxe macros one.
Limitations
+56
View File
@@ -1,4 +1,9 @@
import haxe.ds.EnumValueMap;
import haxe.ds.Option;
import hscript.Macro;
import hscript.Tools;
import hscript.Async;
import hscript.Printer;
import haxe.unit.*;
class Test extends TestCase {
@@ -73,6 +78,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);
@@ -95,6 +101,56 @@ class Test extends TestCase {
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();
runner.add(new Test());
+16 -13
View File
@@ -6,19 +6,22 @@ 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
- haxelib install hxcpp > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxjava > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxcpp > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxjava > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1
- haxelib install hx3compat > log.txt || type log.txt && cmd /C exit 1
- haxelib dev hscript .
- haxelib list
@@ -28,12 +31,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
View File
@@ -1,2 +1,3 @@
-main Test
-dce no
-lib hx3compat
+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.2.0",
"releasenote": "",
"contributors": ["ncannasse"]
}
+1 -1
View File
@@ -1 +1 @@
build-flash.hxml
bin/build-flash.hxml
+494
View File
@@ -0,0 +1,494 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
class Async {
var varNames : Array<String>;
var currentFun : String;
var currentLoop : Expr;
var currentBreak : Expr -> Expr;
var uid = 0;
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);
inline static function expr( e : Expr ) {
return #if hscriptPos e.e #else e #end;
}
inline static function mk( e, inf : Expr ) : Expr {
return #if hscriptPos { e : e, pmin : inf.pmin, pmax : inf.pmax, origin : inf.origin, line : inf.line } #else e #end;
}
/**
Convert a script into asynchronous one.
- calls such as foo(a,b,c) are translated to a_foo(function(r) ...rest, a,b,c) where r is the result value
- object access such obj.bar(a,b,c) are translated to obj.a_bar(function(r) ...rest, a, b, c)
- @async expr will execute the expression but continue without waiting for it to finish
- @split [ e1, e2, e3 ] is transformed to split(function(_) ...rest, [e1, e2, e3]) which
should execute asynchronously all expressions - until they return - before continuing the execution
- for(i in v) block; loops are translated to the following:
var _i = makeIterator(v);
function _loop() {
if( !_i.hasNext() ) return;
var v = _i.next();
block(function(_) _loop());
}
_loop()
- while loops are translated similar to for loops
- break and continue are correctly handled
- you can use @sync <expr> to disable async transformation in some code parts (for performance reason)
- a few expressions are still not supported (complex calls, try/catch, and a few others)
In these examples ...rest represents the continuation of execution of the script after the expression
**/
public static function toAsync( e : Expr, topLevelSync = false ) {
var a = new Async();
return a.build(e, topLevelSync);
}
public function build( e : Expr, topLevelSync = false ) {
if( topLevelSync ) {
return buildSync(e,null);
} else {
var nothing = ignore();
return new Async().toCps(e, nothing, nothing);
}
}
function buildSync( e : Expr, exit : Expr ) : Expr {
switch( expr(e) ) {
case EFunction(_):
return toCps(e, null, null);
case EBlock(el):
var v = saveVars();
for( e in el )
switch( expr(e) ) {
case EFunction(_, _, name, _) if( name != null ): varNames.push(name);
default:
}
var e = block([for(e in el) buildSync(e,exit)], e);
restoreVars(v);
return e;
case EMeta("async", _, e):
return toCps(e, ignore(), ignore());
case EBreak if( currentBreak != null ):
return currentBreak(e);
case EContinue if( currentLoop != null ):
return block([call(currentLoop, [nullId], e), mk(EReturn(),e)],e);
case EFor(_), EWhile(_):
var oldLoop = currentLoop, oldBreak = currentBreak;
currentLoop = null;
currentBreak = null;
e = Tools.map(e, buildSync.bind(_, exit));
currentLoop = oldLoop;
currentBreak = oldBreak;
return e;
case EReturn(eret) if( exit != null ):
return block([call(exit,[eret == null ? nullId : eret], e), mk(EReturn(),e)], e);
default:
return Tools.map(e, buildSync.bind(_, exit));
}
}
public function new() {
varNames = [];
}
function ignore(?e) : Expr {
var inf = e == null ? nullExpr : e;
return fun("_", block(e == null ? [] : [e],inf));
}
inline function ident(str, e) {
return mk(EIdent(str), e);
}
inline function fun(arg:String, e, ?name) {
return mk(EFunction([{ name : arg, t : null }], e, name), e);
}
inline function funs(arg:Array<String>, e, ?name) {
return mk(EFunction([for( a in arg ) { name : a, t : null }], e, name), e);
}
inline function block(arr, e) {
return mk(EBlock(arr), e);
}
inline function field(e, f, inf) {
return mk(EField(e, f), inf);
}
inline function binop(op, e1, e2, inf) {
return mk(EBinop(op, e1, e2), inf);
}
inline function call(e, args, inf) {
return mk(ECall(e, args), inf);
}
function retNull(e) : Expr {
return call(e, [nullId],e);
}
function makeCall( ecall, args : Array<Expr>, rest : Expr, exit, sync = false ) {
var names = [for( i in 0...args.length ) "_a"+uid++];
var rargs = [for( i in 0...args.length ) ident(names[i],ecall)];
if( !sync )
rargs.unshift(rest);
var rest = mk(sync ? ECall(rest,[call(ecall, rargs,ecall)]) : ECall(ecall, rargs), ecall);
var i = args.length - 1;
while( i >= 0 ) {
rest = toCps(args[i], fun(names[i], rest), exit);
i--;
}
return rest;
}
var syncFlag : Bool;
function isSync( e : Expr ) {
syncFlag = true;
checkSync(e);
return syncFlag;
}
function checkSync( e : Expr ) {
if( !syncFlag )
return;
switch( expr(e) ) {
case ECall(_), EFunction(_):
syncFlag = false;
case EMeta("sync" | "async", _, _):
// isolated from the sync part
default:
Tools.iter(e, checkSync);
}
}
function saveVars() {
return varNames.length;
}
function restoreVars(k) {
while( varNames.length > k ) varNames.pop();
}
public function toCps( e : Expr, rest : Expr, exit : Expr ) : Expr {
if( isSync(e) )
return call(rest, [buildSync(e, exit)],e);
switch( expr(e) ) {
case EBlock(el):
var el = el.copy();
var vold = saveVars();
// local recursion
for( e in el )
switch( expr(e) ) {
case EFunction(_, _, name, null): varNames.push(name);
default:
}
while( el.length > 0 ) {
var e = toCps(el.pop(), rest, exit);
rest = ignore(e);
}
restoreVars(vold);
return retNull(rest);
case EFunction(args, body, name, t):
var vold = saveVars();
if( name != null )
varNames.push(name);
for( a in args )
varNames.push(a.name);
args.unshift( { name : "_onEnd", t : null } );
var frest = ident("_onEnd",e);
var oldFun = currentFun;
currentFun = name;
var body = toCps(body, frest, frest);
var f = mk(EFunction(args, body, name, t),e);
restoreVars(vold);
return rest == null ? f : call(rest, [f],e);
case EParent(e):
return mk(EParent(toCps(e, rest, exit)),e);
case EMeta("sync", _, e):
return call(rest,[buildSync(e,exit)],e);
case EMeta("async", _, e):
var nothing = ignore();
return block([toCps(e,nothing,nothing),retNull(rest)],e);
case EMeta("split", _, e):
var args = switch( expr(e) ) { case EArrayDecl(el): el; default: throw "@split expression should be an array"; };
var args = [for( a in args ) fun("_rest", toCps(block([a],a), ident("_rest",a), exit))];
return call(ident("split",e), [rest, mk(EArrayDecl(args),e)],e);
case ECall(expr(_) => EIdent(i), args):
return makeCall( ident( varNames.indexOf(i) < 0 ? "a_" + i : i,e) , args, rest, exit);
case ECall(expr(_) => EField(e, f), args):
return makeCall(field(e,"a_"+f,e), args, rest, exit);
case EFor(v, eit, eloop):
var id = ++uid;
var it = ident("_i" + id,e);
var oldLoop = currentLoop, oldBreak = currentBreak;
var loop = ident("_loop" + id,e);
currentLoop = loop;
currentBreak = function(inf) return block([call(rest, [nullId], inf), mk(EReturn(),inf)], inf);
var efor = block([
mk(EVar("_i" + id, call(ident("makeIterator",eit),[eit],eit)),eit),
fun("_", block([
mk(EIf(mk(EUnop("!", true, call( field(it, "hasNext", it), [], it)),it), currentBreak(it)),it),
mk(EVar(v, call(field(it, "next",it), [], it)), it),
toCps(eloop, loop, exit),
], it),"_loop" + id),
call(loop, [nullId], e),
], e);
currentLoop = oldLoop;
currentBreak = oldBreak;
return efor;
case EUnop(op = "!", prefix, eop):
return toCps(eop, fun("_r",call(rest, [mk(EUnop(op, prefix, ident("_r",e)),e)], e)), exit);
case EBinop(op, e1, e2):
switch( op ) {
case "=", "+=", "-=", "/=", "*=", "%=", "&=", "|=", "^=":
switch( expr(e1) ) {
case EIdent(_):
var id = "_r" + uid++;
return toCps(e2, fun(id, call(rest, [binop(op, e1, ident(id,e1),e1)], e1)), exit);
case EField(ef1, f):
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(ef1, fun(id1, toCps(e2, fun(id2, call(rest, [binop(op, field(ident(id1, e1), f, ef1), ident(id2, e2), e)], e)), exit)), exit);
case EArray(earr, eindex):
var idArr = "_r" + uid++;
var idIndex = "_r" + uid++;
var idVal = "_r" + uid++;
return toCps(earr,fun(idArr, toCps(eindex, fun(idIndex, toCps(e2,
fun(idVal, call(rest, [binop(op, mk(EArray(ident(idArr,earr), ident(idIndex,eindex)),e1), ident(idVal,e1), e)], e))
, exit)), exit)),exit);
default:
throw "assert " + e1;
}
case "||":
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(e1, fun(id1, mk(EIf(binop("==", ident(id1,e1), ident("true",e1), e1),call(rest,[ident("true",e1)],e1),toCps(e2, rest, exit)),e)), exit);
case "&&":
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(e1, fun(id1, mk(EIf(binop("!=", ident(id1,e1), ident("true",e1), e1),call(rest,[ident("false",e1)],e1),toCps(e2, rest, exit)),e)), exit);
default:
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(e1, fun(id1, toCps(e2, fun(id2, call(rest, [binop(op, ident(id1,e1), ident(id2,e2), e)], e)), exit)), exit);
}
case EIf(cond, e1, e2), ETernary(cond, e1, e2):
return toCps(cond, fun("_c", mk(EIf(ident("_c",cond), toCps(e1, rest, exit), e2 == null ? retNull(rest) : toCps(e2, rest, exit)),e)), exit);
case EWhile(cond, ewh):
var id = ++uid;
var loop = ident("_loop" + id, cond);
var oldLoop = currentLoop, oldBreak = currentBreak;
currentLoop = loop;
currentBreak = function(e) return block([call(rest, [nullId], e), mk(EReturn(),e)],e);
var ewhile = block([
fun("_r",
toCps(cond, fun("_c", mk(EIf(ident("_c", cond), toCps(ewh, loop, exit), call(rest, [nullId], cond)),cond)), exit)
, "_loop"+id),
call(loop, [nullId], cond),
],e);
currentLoop = oldLoop;
currentBreak = oldBreak;
return ewhile;
case EReturn(eret):
return eret == null ? call(exit, [nullId], e) : toCps(eret, exit, exit);
case EObject(fields):
var id = "_o" + uid++;
var rest = call(rest, [ident(id,e)], e);
fields.reverse();
for( f in fields )
rest = toCps(f.e, fun("_r", block([
binop("=", mk(EField(ident(id,f.e), f.name),f.e), ident("_r",f.e), f.e),
rest,
],f.e)),exit);
return block([
mk(EVar(id, mk(EObject([]),e)),e),
rest,
],e);
case EArrayDecl(el):
var id = "_a" + uid++;
var rest = call(rest, [ident(id,e)], e);
var i = el.length - 1;
while( i >= 0 ) {
var e = el[i];
rest = toCps(e, fun("_r", block([
binop("=", mk(EArray(ident(id,e), mk(EConst(CInt(i)),e)),e), ident("_r",e), e),
rest,
],e)), exit);
i--;
}
return block([
mk(EVar(id, mk(EArrayDecl([]),e)),e),
rest,
],e);
case EArray(earr, eindex):
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(earr, fun(id1, toCps(eindex, fun(id2, call(rest, [mk(EArray(ident(id1,e), ident(id2,e)),e)], e)), exit)), exit);
case EVar(v, t, ev):
if( ev == null )
return block([e, call(rest, [nullId],e)], e);
return block([
mk(EVar(v, t),e),
toCps(ev, fun("_r", block([binop("=", ident(v,e), ident("_r",e), e), call(rest,[nullId],e)], e)), exit),
],e);
case EConst(_), EIdent(_), EUnop(_), EField(_):
return call(rest, [e], e);
case ENew(cl, args):
var names = [for( i in 0...args.length ) "_a"+uid++];
var rargs = [for( i in 0...args.length ) ident(names[i], args[i])];
var rest = call(rest,[mk(ENew(cl, rargs),e)],e);
var i = args.length - 1;
while( i >= 0 ) {
rest = toCps(args[i], fun(names[i], rest), exit);
i--;
}
return rest;
case EBreak:
if( currentBreak == null ) throw "Break outside loop";
return currentBreak(e);
case EContinue:
if( currentLoop == null ) throw "Continue outside loop";
return block([call(currentLoop, [nullId], e), mk(EReturn(),e)], e);
case ESwitch(v, cases, def):
var cases = [for( c in cases ) { values : c.values, expr : toCps(c.expr, rest, exit) } ];
return toCps(v, mk(EFunction([ { name : "_c", t : null } ], mk(ESwitch(ident("_c",v), cases, def == null ? retNull(rest) : toCps(def, rest, exit)),e)),e), exit );
case EThrow(v):
return toCps(v, mk(EFunction([ { name : "_v", t : null } ], mk(EThrow(v),v)), v), exit);
//case EDoWhile(_), ETry(_), ECall(_):
default:
throw "Unsupported async expression " + Printer.toString(e);
}
}
}
class AsyncInterp extends Interp {
public function setContext( api : Dynamic ) {
var funs = new Array();
for( v in variables.keys() )
if( Reflect.isFunction(variables.get(v)) )
funs.push({ v : v, obj : null });
variables.set("split", split);
variables.set("makeIterator", makeIterator);
var c = Type.getClass(api);
for( f in (c == null ? Reflect.fields(api) : Type.getInstanceFields(c)) ) {
var fv = Reflect.field(api, f);
if( !Reflect.isFunction(fv) ) continue;
if( f.charCodeAt(0) == "_".code ) f = f.substr(1);
variables.set(f, fv);
// create the async wrapper if doesn't exists
if( f.substr(0, 2) != "a_" )
funs.push({ v : f, obj : api });
}
for( v in funs ) {
if( variables.exists("a_" + v.v) ) continue;
var fv : Dynamic = variables.get(v.v);
var obj = v.obj;
variables.set("a_" + v.v, Reflect.makeVarArgs(function(args:Array<Dynamic>) {
var onEnd = args.shift();
onEnd(Reflect.callMethod(obj, fv, args));
}));
}
}
public function hasMethod( name : String ) {
var v = variables.get(name);
return v != null && Reflect.isFunction(v);
}
public function callValue( value : Dynamic, args : Array<Dynamic>, ?onResult : Dynamic -> Void, ?vthis : {} ) {
var oldThis = variables.get("this");
if( vthis != null )
variables.set("this", vthis);
if( onResult == null )
onResult = function(_) {};
args.unshift(onResult);
Reflect.callMethod(null, value, args);
variables.set("this", oldThis);
}
public function callAsync( id : String, args, ?onResult, ?vthis : {} ) {
var v = variables.get(id);
if( v == null )
throw "Missing function " + id + "()";
callValue(v, args, onResult, vthis);
}
function split( rest : Dynamic -> Void, args : Array<Dynamic> ) {
if( args.length == 0 )
rest(null);
else {
var count = args.length;
function next(_) {
if( --count == 0 ) rest(null);
}
for( a in args )
a(next);
}
}
override function fcall( o : Dynamic, f : String, args : Array<Dynamic> ) : Dynamic {
var m = Reflect.field(o, f);
if( m == null ) {
if( f.substr(0, 2) == "a_" ) {
m = Reflect.field(o, f.substr(2));
// fallback on sync version
if( m != null ) {
var onEnd = args.shift();
onEnd(call(o, m, args));
return null;
}
// fallback on generic script
m = Reflect.field(o, "scriptCall");
if( m != null ) {
call(o, m, [args.shift(), f.substr(2), args]);
return null;
}
} else {
// fallback on generic script
m = Reflect.field(o, "scriptCall");
if( m != null ) {
var result : Dynamic = null;
call(o, m, [function(r) result = r, f, args]);
return result;
}
}
error(ECustom(o + " has no method " + f));
}
return call(o, m, args);
}
}
+54 -28
View File
@@ -1,26 +1,23 @@
/*
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (C)2008-2017 Haxe Foundation
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
@@ -74,6 +71,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 +86,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 +106,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 +137,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 +185,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);
@@ -233,12 +244,19 @@ class Bytes {
}
bout.addByte(255);
if( def == null ) bout.addByte(255) else doEncode(def);
case EMeta(name,args,e):
doEncodeString(name);
bout.addByte(args == null ? 0 : args.length + 1);
if( args != null ) for( e in args ) doEncode(e);
doEncode(e);
}
}
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 +365,14 @@ class Bytes {
}
var def = doDecode();
ESwitch(e, cases, def);
case 24:
var cond = doDecode();
EDoWhile(cond,doDecode());
case 25:
var name = doDecodeString();
var count = bin.get(pin++);
var args = count == 0 ? null : [for( i in 0...count - 1 ) doDecode()];
EMeta(name, args, doDecode());
case 255:
null;
default:
@@ -365,4 +391,4 @@ class Bytes {
return b.doDecode();
}
}
}
+95 -23
View File
@@ -1,26 +1,23 @@
/*
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (C)2008-2017 Haxe Foundation
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
@@ -38,6 +35,8 @@ typedef Expr = {
var e : ExprDef;
var pmin : Int;
var pmax : Int;
var origin : String;
var line : Int;
}
enum ExprDef {
#else
@@ -67,14 +66,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 Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
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 +86,17 @@ 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;
}
public function toString(): String {
return Printer.errorToString(this);
}
}
enum ErrorDef {
@@ -97,8 +107,70 @@ enum Error {
EUnexpected( s : String );
EUnterminatedString;
EUnterminatedComment;
EInvalidPreprocessor( msg : String );
EUnknownVariable( v : String );
EInvalidIterator( v : String );
EInvalidOp( op : String );
EInvalidAccess( f : String );
ECustom( msg : String );
}
enum ModuleDecl {
DPackage( path : Array<String> );
DImport( path : Array<String>, ?everything : Bool );
DClass( c : ClassDecl );
DTypedef( c : TypeDecl );
}
typedef ModuleType = {
var name : String;
var params : {}; // TODO : not yet parsed
var meta : Metadata;
var isPrivate : Bool;
}
typedef ClassDecl = {> ModuleType,
var extend : Null<CType>;
var implement : Array<CType>;
var fields : Array<FieldDecl>;
var isExtern : Bool;
}
typedef TypeDecl = {> ModuleType,
var t : CType;
}
typedef FieldDecl = {
var name : String;
var meta : Metadata;
var kind : FieldKind;
var access : Array<FieldAccess>;
}
enum FieldAccess {
APublic;
APrivate;
AInline;
AOverride;
AStatic;
AMacro;
}
enum FieldKind {
KFunction( f : FunctionDecl );
KVar( v : VarDecl );
}
typedef FunctionDecl = {
var args : Array<Argument>;
var expr : Expr;
var ret : Null<CType>;
}
typedef VarDecl = {
var get : Null<String>;
var set : Null<String>;
var expr : Null<Expr>;
var type : Null<CType>;
}
+193 -65
View File
@@ -1,34 +1,32 @@
/*
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (C)2008-2017 Haxe Foundation
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import haxe.PosInfos;
import hscript.Expr;
private enum Stop {
SBreak;
SContinue;
SReturn( v : Dynamic );
SReturn;
}
class Interp {
@@ -46,6 +44,7 @@ class Interp {
var depth : Int;
var inTry : Bool;
var declared : Array<{ n : String, old : { r : Dynamic } }>;
var returnValue : Dynamic;
#if hscriptPos
var curExpr : Expr;
@@ -63,10 +62,23 @@ 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", Reflect.makeVarArgs(function(el) {
var inf = posInfos();
var v = el.shift();
if( el.length > 0 ) inf.customParams = el;
haxe.Log.trace(Std.string(v), inf);
}));
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 +131,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 +166,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 +207,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)?"++":"--"));
}
@@ -214,7 +253,10 @@ class Interp {
switch( e ) {
case SBreak: throw "Invalid break";
case SContinue: throw "Invalid continue";
case SReturn(v): return v;
case SReturn:
var v = returnValue;
returnValue = null;
return v;
}
}
return null;
@@ -246,13 +288,18 @@ class Interp {
#end
}
inline function error(e : #if hscriptPos ErrorDef #else Error #end ) : Dynamic {
#if hscriptPos
throw new Error(e, curExpr.pmin, curExpr.pmax);
inline function error(e : #if hscriptPos ErrorDef #else Error #end, rethrow=false ) : Dynamic {
#if hscriptPos var e = new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line); #end
if( rethrow ) this.rethrow(e) else throw e;
return null;
}
inline function rethrow( e : Dynamic ) {
#if hl
hl.Api.rethrow(e);
#else
throw e;
#end
return null;
}
function resolve( id : String ) : Dynamic {
@@ -338,6 +385,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;
@@ -346,7 +396,8 @@ class Interp {
case EContinue:
throw SContinue;
case EReturn(e):
throw SReturn((e == null)?null:expr(e));
returnValue = e == null ? null : expr(e);
throw SReturn;
case EFunction(params,fexpr,name,_):
var capturedLocals = duplicate(locals);
var me = this;
@@ -417,12 +468,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 +572,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 ) {
@@ -490,7 +604,7 @@ class Interp {
switch(err) {
case SContinue:
case SBreak: break;
case SReturn(_): throw err;
case SReturn: throw err;
}
}
}
@@ -498,8 +612,8 @@ class Interp {
}
function makeIterator( v : Dynamic ) : Iterator<Dynamic> {
#if (flash && !flash9)
if( v.iterator != null ) v = v.iterator();
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
if ( v.iterator != null ) v = v.iterator();
#else
try v = v.iterator() catch( e : Dynamic ) {};
#end
@@ -519,25 +633,39 @@ class Interp {
switch( err ) {
case SContinue:
case SBreak: break;
case SReturn(_): throw err;
case SReturn: throw err;
}
}
}
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 {
+39 -30
View File
@@ -1,26 +1,23 @@
/*
* Copyright (c) 2011, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (C)2008-2017 Haxe Foundation
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr.Error;
@@ -79,6 +76,9 @@ class Macro {
#if haxe3
case OpArrow: "=>";
#end
#if (haxe_ver >= 4)
case OpIn: "in";
#end
};
binops.set(str, op);
if( assign )
@@ -129,8 +129,10 @@ class Macro {
TFunction(map(args,convertType), convertType(ret));
case CTAnon(fields):
var tf = [];
for( f in fields )
tf.push( { name : f.name, meta : [], doc : null, access : [], kind : FVar(convertType(f.t),null), pos : p } );
for( f in fields ) {
var meta = f.meta == null ? [] : [for( m in f.meta ) { name : m.name, params : m.params == null ? [] : [for( e in m.params ) convert(e)], pos : p }];
tf.push( { name : f.name, meta : meta, doc : null, access : [], kind : FVar(convertType(f.t), null), pos : p } );
}
TAnonymous(tf);
};
}
@@ -180,14 +182,18 @@ class Macro {
EIf(convert(c), convert(e1), e2 == null ? null : convert(e2));
case EWhile(c, e):
EWhile(convert(c), convert(e), true);
#if (haxe_211 || haxe3)
case EDoWhile(c, e):
EWhile(convert(c), convert(e), false);
case EFor(v, it, efor):
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#else
case EFor(v, it, e):
EFor(v, convert(it), convert(e));
#end
#if (haxe_ver >= 4)
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EBinop(OpIn,{ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#elseif (haxe_211 || haxe3)
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#else
EFor(v, convert(it), convert(efor));
#end
case EBreak:
EBreak;
case EContinue:
@@ -229,7 +235,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 }
}
}
}
+593 -163
View File
File diff suppressed because it is too large Load Diff
+70 -1
View File
@@ -1,3 +1,24 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
@@ -16,6 +37,13 @@ class Printer {
return buf.toString();
}
public function typeToString( t : CType ) {
buf = new StringBuf();
tabs = "";
type(t);
return buf.toString();
}
inline function add<T>(s:T) buf.add(s);
function type( t : CType ) {
@@ -148,6 +176,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);
@@ -252,6 +286,20 @@ class Printer {
add(";\n");
}
add("}");
case EMeta(name, args, e):
add("@");
add(name);
if( args != null && args.length > 0 ) {
add("(");
var first = true;
for( a in args ) {
if( first ) first = false else add(", ");
expr(e);
}
add(")");
}
add(" ");
expr(e);
}
}
@@ -259,4 +307,25 @@ class Printer {
return new Printer().exprToString(e);
}
}
public static function errorToString( e : Expr.Error ) {
var message = switch( #if hscriptPos e.e #else e #end ) {
case EInvalidChar(c): "Invalid character: '"+String.fromCharCode(c)+"' ("+c+")";
case EUnexpected(s): "Unexpected token: \""+s+"\"";
case EUnterminatedString: "Unterminated string";
case EUnterminatedComment: "Unterminated comment";
case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")";
case EUnknownVariable(v): "Unknown variable: "+v;
case EInvalidIterator(v): "Invalid iterator: "+v;
case EInvalidOp(op): "Invalid operator: "+op;
case EInvalidAccess(f): "Invalid access to field " + f;
case ECustom(msg): msg;
};
#if hscriptPos
return e.origin + ":" + e.line + ": " + message;
#else
return message;
#end
}
}
+34 -3
View File
@@ -1,10 +1,31 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
class Tools {
public static function iter( e : Expr, f : Expr -> Void ) {
switch( e ) {
switch( #if hscriptPos e.e #else e #end ) {
case EConst(_), EIdent(_):
case EVar(_, _, e): if( e != null ) f(e);
case EParent(e): f(e);
@@ -15,6 +36,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);
@@ -33,12 +55,17 @@ class Tools {
f(c.expr);
}
if( def != null ) f(def);
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
}
}
public static function map( e : Expr, f : Expr -> Expr ) {
#if hscriptPos
var edef = switch( e.e ) {
#else
return switch( e ) {
case EConst(_), EIdent(_): e;
#end
case EConst(_), EIdent(_), EBreak, EContinue: #if hscriptPos e.e #else e #end;
case EVar(n, t, e): EVar(n, t, if( e != null ) f(e) else null);
case EParent(e): EParent(f(e));
case EBlock(el): EBlock([for( e in el ) f(e)]);
@@ -48,8 +75,8 @@ 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);
case EReturn(e): EReturn(if( e != null ) f(e) else null);
case EArray(e, i): EArray(f(e),f(i));
@@ -60,7 +87,11 @@ class Tools {
case EObject(fl): EObject([for( fi in fl ) { name : fi.name, e : f(fi.e) }]);
case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2));
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));
}
#if hscriptPos
return { e : edef, pmin : e.pmin, pmax : e.pmax, origin : e.origin, line : e.line };
#end
}
}
+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