Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b32dde3c91 | ||
|
|
b9a566350b | ||
|
|
ce9ce674ea | ||
|
|
b8641779bd | ||
|
|
5e620d784e | ||
|
|
013bcfaffb | ||
|
|
2504c96927 | ||
|
|
e2f4d1481e | ||
|
|
ea3d68573b | ||
|
|
c6cb594ef1 | ||
|
|
948123bc7a | ||
|
|
68f5b26af9 | ||
|
|
5d493630b1 | ||
|
|
f4db6faa80 | ||
|
|
e340f7f5ad | ||
|
|
b4d923b74c | ||
|
|
965f334d59 | ||
|
|
54463b78d2 | ||
|
|
600aec1f50 | ||
|
|
bcfbe81979 | ||
|
|
31e8851bcc | ||
|
|
f464767ee7 | ||
|
|
22eb58b3de | ||
|
|
0daee20545 | ||
|
|
d98073dc33 | ||
|
|
fb199e7dea | ||
|
|
6cea0d97c2 | ||
|
|
058dd2e01e | ||
|
|
975d122491 | ||
|
|
eef4c66374 | ||
|
|
5ce4fbd74d | ||
|
|
f4d8cff26b | ||
|
|
46b6b3c151 | ||
|
|
796b217dec | ||
|
|
1ccc35f464 | ||
|
|
2ed6f15fe1 | ||
|
|
575040be65 | ||
|
|
206959adbd | ||
|
|
dd1c97b6af | ||
|
|
85463dcff0 | ||
|
|
7ff816417e | ||
|
|
3fa2f3898a | ||
|
|
514ce9eec2 | ||
|
|
5bc357b4b3 | ||
|
|
56ddc3c24e | ||
|
|
e407b2a307 | ||
|
|
1ac194ed1d | ||
|
|
62bf5d4cc9 | ||
|
|
27093064a9 | ||
|
|
860a3018a7 | ||
|
|
eb3992dbdb | ||
|
|
8c5f9cc1d3 | ||
|
|
ed78703090 | ||
|
|
29b61bcee9 | ||
|
|
0ff49845a7 | ||
|
|
c17366b2b1 | ||
|
|
5da267fb31 | ||
|
|
dffa3345d0 | ||
|
|
a23c767fb0 | ||
|
|
5d6ec51302 | ||
|
|
585f277bf5 | ||
|
|
aae5f431cb | ||
|
|
4eb84e5c32 |
+18
-22
@@ -4,12 +4,11 @@ os:
|
|||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
|
|
||||||
sudo: false
|
dist: bionic
|
||||||
dist: trusty
|
|
||||||
|
|
||||||
haxe:
|
haxe:
|
||||||
- "3.2.1"
|
- "3.4.7"
|
||||||
- "3.4.2"
|
- "4.0.3"
|
||||||
- development
|
- development
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
@@ -20,37 +19,31 @@ addons:
|
|||||||
- g++-multilib
|
- g++-multilib
|
||||||
# Python
|
# Python
|
||||||
- python3
|
- python3
|
||||||
|
# PHP
|
||||||
|
- php-cli
|
||||||
|
- php-mbstring
|
||||||
# C#
|
# C#
|
||||||
- mono-devel
|
- mono-devel
|
||||||
- mono-mcs
|
- mono-mcs
|
||||||
# Flash
|
|
||||||
- libglib2.0
|
|
||||||
- libfreetype6
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
# os-specific config
|
# os-specific config
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||||
export DISPLAY=:99.0;
|
|
||||||
export AUDIODEV=null;
|
|
||||||
phpenv global 7.0;
|
|
||||||
elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
|
||||||
brew update;
|
brew update;
|
||||||
brew install mono;
|
brew install mono;
|
||||||
brew install python3;
|
brew install php;
|
||||||
brew tap homebrew/homebrew-php;
|
|
||||||
brew install php71;
|
|
||||||
fi
|
fi
|
||||||
# Download and setup a standalone flash player debugger
|
|
||||||
- haxe flash/install.hxml
|
|
||||||
# Install haxelibs
|
# Install haxelibs
|
||||||
- if [ "${TRAVIS_HAXE_VERSION}" = "development" ]; then
|
- if [ "${TRAVIS_HAXE_VERSION}" = "development" ]; then
|
||||||
haxelib git hxcpp https://github.com/HaxeFoundation/hxcpp.git;
|
haxelib git hxcpp https://github.com/HaxeFoundation/hxcpp.git;
|
||||||
|
else
|
||||||
|
haxelib install hxcpp;
|
||||||
|
fi
|
||||||
|
- if [ "${TRAVIS_HAXE_VERSION}" = "development" ] || [ "${TRAVIS_HAXE_VERSION}" = "3.2.1" ]; then
|
||||||
pushd $(haxelib path hxcpp | head -1);
|
pushd $(haxelib path hxcpp | head -1);
|
||||||
pushd tools/hxcpp; haxe compile.hxml; popd;
|
pushd tools/hxcpp; haxe compile.hxml; popd;
|
||||||
pushd project; neko build.n; popd;
|
pushd project; neko build.n; popd;
|
||||||
popd;
|
popd;
|
||||||
else
|
|
||||||
haxelib install hxcpp;
|
|
||||||
fi
|
fi
|
||||||
- haxelib install hxjava
|
- haxelib install hxjava
|
||||||
- haxelib install hxcs
|
- haxelib install hxcs
|
||||||
@@ -63,11 +56,14 @@ script:
|
|||||||
haxe build.hxml &&
|
haxe build.hxml &&
|
||||||
popd
|
popd
|
||||||
- haxe bin/build-interp.hxml
|
- haxe bin/build-interp.hxml
|
||||||
|
- haxe bin/build-interp.hxml -D hscriptPos
|
||||||
- haxe bin/build-neko.hxml && neko bin/Test.n
|
- haxe bin/build-neko.hxml && neko bin/Test.n
|
||||||
- haxe bin/build-js.hxml && node bin/Test.js
|
- haxe bin/build-js.hxml && node bin/Test.js
|
||||||
- haxe bin/build-java.hxml && java -jar bin/Test.jar
|
- haxe bin/build-java.hxml && java -jar bin/Test.jar
|
||||||
- haxe bin/build-cs.hxml && mono bin/bin/Test.exe
|
# Only test C# for Haxe 4+
|
||||||
|
- if [[ $(haxe -version 2&>1 | head -c 1) > 3 ]]; then
|
||||||
|
haxe bin/build-cs.hxml && mono bin/bin/Test.exe;
|
||||||
|
fi
|
||||||
- haxe bin/build-cpp.hxml && ./bin/Test
|
- 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 -D php7 && php bin/index.php
|
||||||
- haxe bin/build-php.hxml && php bin/index.php
|
|
||||||
- haxe bin/build-python.hxml && python3 bin/Test.py
|
- haxe bin/build-python.hxml && python3 bin/Test.py
|
||||||
|
|||||||
Vendored
+16
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// Utilisez IntelliSense pour en savoir plus sur les attributs possibles.
|
||||||
|
// Pointez pour afficher la description des attributs existants.
|
||||||
|
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "HashLink (launch)",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "hl",
|
||||||
|
"hxml": "hscript.hxml",
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"preLaunchTask": "Build"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+16
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build",
|
||||||
|
"type": "hxml",
|
||||||
|
"file": "hscript.hxml",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -68,24 +68,36 @@ You can use `parser.allowMetadata` to parse metadata before expressions on in an
|
|||||||
|
|
||||||
You can use `new hscript.Macro(pos).convert(ast)` to convert an hscript AST to a Haxe macros one.
|
You can use `new hscript.Macro(pos).convert(ast)` to convert an hscript AST to a Haxe macros one.
|
||||||
|
|
||||||
|
You can use `hscript.Checker` in order to type check and even get completion, using `haxe -xml` output for type information.
|
||||||
|
|
||||||
Limitations
|
Limitations
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
Compared to Haxe, limitations are :
|
Compared to Haxe, limitations are :
|
||||||
|
|
||||||
- no type declarations (classes, enums, typedefs) : only expressions
|
|
||||||
- `switch` construct is supported but not pattern matching (no variable capture, we use strict equality to compare `case` values and `switch` value)
|
- `switch` construct is supported but not pattern matching (no variable capture, we use strict equality to compare `case` values and `switch` value)
|
||||||
- only one variable declaration is allowed in `var`
|
- only one variable declaration is allowed in `var`
|
||||||
- the parser supports optional types for `var` and `function` if `allowTypes` is set, but the interpreter ignores them
|
- the parser supports optional types for `var` and `function` if `allowTypes` is set, but the interpreter ignores them
|
||||||
- you can enable per-expression position tracking by compiling with `-D hscriptPos`
|
- you can enable per-expression position tracking by compiling with `-D hscriptPos`
|
||||||
|
- you can parse some type declarations (import, class, typedef, etc.) with parseModule
|
||||||
|
|
||||||
Install
|
Install
|
||||||
-------
|
-------
|
||||||
|
|
||||||
In order to install Haxe Script, use `haxelib install hscript` and compile your program with `-lib hscript`.
|
In order to install Haxe Script, use `haxelib install hscript` and compile your program with `-lib hscript`.
|
||||||
|
|
||||||
There are only three files in hscript :
|
These are the main required files in hscript :
|
||||||
|
|
||||||
- `hscript.Expr` : contains enums declarations
|
- `hscript.Expr` : contains enums declarations
|
||||||
- `hscript.Parser` : a small parser that turns a string into an expression structure (AST)
|
- `hscript.Parser` : a small parser that turns a string into an expression structure (AST)
|
||||||
- `hscript.Interp` : a small interpreter that execute the AST and returns the latest evaluated value
|
- `hscript.Interp` : a small interpreter that execute the AST and returns the latest evaluated value
|
||||||
|
|
||||||
|
Some other optional files :
|
||||||
|
|
||||||
|
- `hscript.Async` : converts Expr into asynchronous version
|
||||||
|
- `hscript.Bytes` : Expr serializer/unserializer
|
||||||
|
- `hscript.Checker` : type checking and completion for hscript Expr
|
||||||
|
- `hscript.Macro` : convert Haxe macro into hscript Expr
|
||||||
|
- `hscript.Printer` : convert hscript Expr to String
|
||||||
|
- `hscript.Tools` : utility functions (map/iter)
|
||||||
|
|
||||||
@@ -4,10 +4,11 @@ import hscript.Macro;
|
|||||||
import hscript.Tools;
|
import hscript.Tools;
|
||||||
import hscript.Async;
|
import hscript.Async;
|
||||||
import hscript.Printer;
|
import hscript.Printer;
|
||||||
|
import hscript.Checker;
|
||||||
import haxe.unit.*;
|
import haxe.unit.*;
|
||||||
|
|
||||||
class Test extends TestCase {
|
class Test extends TestCase {
|
||||||
function assertScript(x,v:Dynamic,?vars : Dynamic,allowTypes=false) {
|
function assertScript(x,v:Dynamic,?vars : Dynamic, allowTypes=false, ?pos:haxe.PosInfos) {
|
||||||
var p = new hscript.Parser();
|
var p = new hscript.Parser();
|
||||||
p.allowTypes = allowTypes;
|
p.allowTypes = allowTypes;
|
||||||
var program = p.parseString(x);
|
var program = p.parseString(x);
|
||||||
@@ -18,7 +19,7 @@ class Test extends TestCase {
|
|||||||
for( v in Reflect.fields(vars) )
|
for( v in Reflect.fields(vars) )
|
||||||
interp.variables.set(v,Reflect.field(vars,v));
|
interp.variables.set(v,Reflect.field(vars,v));
|
||||||
var ret : Dynamic = interp.execute(program);
|
var ret : Dynamic = interp.execute(program);
|
||||||
assertEquals(v, ret);
|
assertEquals(v, ret, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test():Void {
|
function test():Void {
|
||||||
@@ -99,6 +100,16 @@ class Test extends TestCase {
|
|||||||
assertScript("var a:Array<Dynamic>=[1,2,4]; a[2]", 4, null, true);
|
assertScript("var a:Array<Dynamic>=[1,2,4]; a[2]", 4, null, true);
|
||||||
assertScript("/**/0", 0);
|
assertScript("/**/0", 0);
|
||||||
assertScript("x=1;x*=-2", -2);
|
assertScript("x=1;x*=-2", -2);
|
||||||
|
assertScript("var f = x -> x + 1; f(3)", 4);
|
||||||
|
assertScript("var f = (x) -> x + 1; f(3)", 4);
|
||||||
|
assertScript("var f = (x:Int) -> x + 1; f(3)", 4);
|
||||||
|
assertScript("var f = (x,y) -> x + y; f(3,1)", 4);
|
||||||
|
assertScript("var f = (x,y:Int) -> x + y; f(3,1)", 4);
|
||||||
|
assertScript("var f = (x:Int,y:Int) -> x + y; f(3,1)", 4);
|
||||||
|
assertScript("var f:Int->Int->Int = (x:Int,y:Int) -> x + y; f(3,1)", 4, null, true);
|
||||||
|
assertScript("var f:(x:Int, y:Int)->Int = (x:Int,y:Int) -> x + y; f(3,1)", 4, null, true);
|
||||||
|
assertScript("var f:(x:Int)->(y:Int, z:Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2)", 6, null, true);
|
||||||
|
assertScript("var f:(x:Int)->(Int, Int)->Int = (x:Int) -> (y:Int, z:Int) -> x + y + z; f(3)(1, 2)", 6, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMap():Void {
|
function testMap():Void {
|
||||||
@@ -152,9 +163,16 @@ class Test extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static function main() {
|
static function main() {
|
||||||
|
#if ((haxe_ver < 4) && php)
|
||||||
|
// uncaught exception: The each() function is deprecated. This message will be suppressed on further calls (errno: 8192)
|
||||||
|
// in file: /Users/travis/build/andyli/hscript/bin/lib/Type.class.php line 178
|
||||||
|
untyped __php__("error_reporting(E_ALL ^ E_DEPRECATED);");
|
||||||
|
#end
|
||||||
|
|
||||||
var runner = new TestRunner();
|
var runner = new TestRunner();
|
||||||
runner.add(new Test());
|
runner.add(new Test());
|
||||||
var succeed = runner.run();
|
var succeed = runner.run();
|
||||||
|
|
||||||
#if sys
|
#if sys
|
||||||
Sys.exit(succeed ? 0 : 1);
|
Sys.exit(succeed ? 0 : 1);
|
||||||
#elseif flash
|
#elseif flash
|
||||||
|
|||||||
+3
-9
@@ -5,18 +5,14 @@ environment:
|
|||||||
HAXELIB_ROOT: C:\projects\haxelib
|
HAXELIB_ROOT: C:\projects\haxelib
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
# http://help.appveyor.com/discussions/problems/5616-not-able-to-build-due-to-problem-in-chocolateyinstallps1
|
||||||
|
- ps: Set-Service wuauserv -StartupType Manual
|
||||||
# Install the haxe chocolatey package (https://chocolatey.org/packages/haxe)
|
# Install the haxe chocolatey package (https://chocolatey.org/packages/haxe)
|
||||||
- cinst haxe -version 3.4.2 -y
|
- cinst haxe -version 4.0.3 -y
|
||||||
- RefreshEnv
|
- RefreshEnv
|
||||||
# Setup haxelib
|
# Setup haxelib
|
||||||
- mkdir "%HAXELIB_ROOT%"
|
- mkdir "%HAXELIB_ROOT%"
|
||||||
- haxelib setup "%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
|
# Install project dependencies
|
||||||
- haxelib install hxcpp > 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 hxjava > log.txt || type log.txt && cmd /C exit 1
|
||||||
@@ -37,6 +33,4 @@ test_script:
|
|||||||
- haxe bin/build-java.hxml && java -jar bin\Test.jar
|
- haxe bin/build-java.hxml && java -jar bin\Test.jar
|
||||||
- haxe bin/build-cs.hxml && bin\bin\Test.exe
|
- haxe bin/build-cs.hxml && bin\bin\Test.exe
|
||||||
- haxe bin/build-cpp.hxml && 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
|
- haxe bin/build-python.hxml && C:\Python34-x64\python.exe bin\Test.py
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
*.exe
|
|
||||||
*.app
|
|
||||||
flashplayerdebugger
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
import Sys.*;
|
|
||||||
import sys.io.File.*;
|
|
||||||
import haxe.*;
|
|
||||||
import haxe.io.*;
|
|
||||||
|
|
||||||
class Install {
|
|
||||||
// https://www.adobe.com/support/flashplayer/downloads.html
|
|
||||||
static var fpDownload(default, never) = switch (systemName()) {
|
|
||||||
case "Linux":
|
|
||||||
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flash_player_sa_linux_debug.x86_64.tar.gz";
|
|
||||||
case "Mac":
|
|
||||||
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flashplayer_25_sa_debug.dmg";
|
|
||||||
case "Windows":
|
|
||||||
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flashplayer_25_sa_debug.exe";
|
|
||||||
case _:
|
|
||||||
throw "unsupported system";
|
|
||||||
}
|
|
||||||
// https://helpx.adobe.com/flash-player/kb/configure-debugger-version-flash-player.html
|
|
||||||
static var mmcfg(default, never) = switch (systemName()) {
|
|
||||||
case "Linux":
|
|
||||||
Path.join([getEnv("HOME"), "mm.cfg"]);
|
|
||||||
case "Mac":
|
|
||||||
"/Library/Application Support/Macromedia/mm.cfg";
|
|
||||||
case "Windows":
|
|
||||||
Path.join([getEnv("HOMEDRIVE") + getEnv("HOMEPATH"), "mm.cfg"]);
|
|
||||||
case _:
|
|
||||||
throw "unsupported system";
|
|
||||||
}
|
|
||||||
// http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7c95.html
|
|
||||||
static var fpTrust(default, never) = switch (systemName()) {
|
|
||||||
case "Linux":
|
|
||||||
Path.join([getEnv("HOME"), ".macromedia/Flash_Player/#Security/FlashPlayerTrust"]);
|
|
||||||
case "Mac":
|
|
||||||
"/Library/Application Support/Macromedia/FlashPlayerTrust";
|
|
||||||
case "Windows":
|
|
||||||
Path.join([getEnv("SYSTEMROOT"), "system32", "Macromed", "Flash", "FlashPlayerTrust"]);
|
|
||||||
case _:
|
|
||||||
throw "unsupported system";
|
|
||||||
}
|
|
||||||
static function main() {
|
|
||||||
switch (systemName()) {
|
|
||||||
case "Linux":
|
|
||||||
// Download and unzip flash player
|
|
||||||
if (command("wget", [fpDownload]) != 0)
|
|
||||||
throw "failed to download flash player";
|
|
||||||
if (command("tar", ["-xf", Path.withoutDirectory(fpDownload), "-C", "flash"]) != 0)
|
|
||||||
throw "failed to extract flash player";
|
|
||||||
case "Mac":
|
|
||||||
// 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
|
|
||||||
download(fpDownload, "flash\\flashplayer.exe");
|
|
||||||
case _:
|
|
||||||
throw "unsupported system";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create a configuration file so the trace log is enabled
|
|
||||||
createDirectory(Path.directory(mmcfg));
|
|
||||||
saveContent(mmcfg, "ErrorReportingEnable=1\nTraceOutputFileEnable=1");
|
|
||||||
|
|
||||||
// Add the current directory as trusted, so exit() can be used
|
|
||||||
createDirectory(fpTrust);
|
|
||||||
saveContent(Path.join([fpTrust, "test.cfg"]), getCwd());
|
|
||||||
}
|
|
||||||
static function download(url:String, saveAs:String):Void {
|
|
||||||
var http = new Http(url);
|
|
||||||
http.onError = function(e) {
|
|
||||||
throw e;
|
|
||||||
};
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
import Sys.*;
|
|
||||||
import sys.FileSystem.*;
|
|
||||||
import sys.io.File.*;
|
|
||||||
import haxe.io.*;
|
|
||||||
|
|
||||||
class Run {
|
|
||||||
// https://helpx.adobe.com/flash-player/kb/configure-debugger-version-flash-player.html
|
|
||||||
static var flashlog(default, never) = switch (systemName()) {
|
|
||||||
case "Linux":
|
|
||||||
Path.join([getEnv("HOME"), ".macromedia/Flash_Player/Logs/flashlog.txt"]);
|
|
||||||
case "Mac":
|
|
||||||
Path.join([getEnv("HOME"), "Library/Preferences/Macromedia/Flash Player/Logs/flashlog.txt"]);
|
|
||||||
case "Windows":
|
|
||||||
Path.join([getEnv("APPDATA"), "Macromedia", "Flash Player", "Logs", "flashlog.txt"]);
|
|
||||||
case _:
|
|
||||||
throw "unsupported system";
|
|
||||||
}
|
|
||||||
static function main() {
|
|
||||||
var args = args();
|
|
||||||
var swf = args[0];
|
|
||||||
var exitCode = switch (systemName()) {
|
|
||||||
case "Linux":
|
|
||||||
// The flash player has some issues with unexplained crashes,
|
|
||||||
// but if it runs about 16 times, it should succeed one of those...
|
|
||||||
var c = -1;
|
|
||||||
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("/Applications/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger", [fullPath(swf)]);
|
|
||||||
case "Windows":
|
|
||||||
command("flash\\flashplayer.exe", [fullPath(swf)]);
|
|
||||||
case _:
|
|
||||||
throw "unsupported platform";
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
-cp flash
|
|
||||||
--run Install
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
-cp flash
|
|
||||||
--run Run
|
|
||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
"url": "https://github.com/HaxeFoundation/hscript",
|
"url": "https://github.com/HaxeFoundation/hscript",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
|
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
|
||||||
"version": "2.2.0",
|
"version": "2.4.0",
|
||||||
"releasenote": "",
|
"releasenote": "Haxe 4.0 final + type checking/completion (hscript.Checker)",
|
||||||
"contributors": ["ncannasse"]
|
"contributors": ["ncannasse"]
|
||||||
}
|
}
|
||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
bin/build-flash.hxml
|
bin/build-each.hxml
|
||||||
|
-hl bin/Test.hl
|
||||||
+72
-37
@@ -22,9 +22,16 @@
|
|||||||
package hscript;
|
package hscript;
|
||||||
import hscript.Expr;
|
import hscript.Expr;
|
||||||
|
|
||||||
|
|
||||||
|
enum VarMode {
|
||||||
|
Defined;
|
||||||
|
ForceSync;
|
||||||
|
}
|
||||||
|
|
||||||
class Async {
|
class Async {
|
||||||
|
|
||||||
var varNames : Array<String>;
|
var definedVars : Array<{ n : String, prev : Null<VarMode> }>;
|
||||||
|
var vars : Map<String,VarMode>;
|
||||||
var currentFun : String;
|
var currentFun : String;
|
||||||
var currentLoop : Expr;
|
var currentLoop : Expr;
|
||||||
var currentBreak : Expr -> Expr;
|
var currentBreak : Expr -> Expr;
|
||||||
@@ -68,35 +75,53 @@ class Async {
|
|||||||
return a.build(e, topLevelSync);
|
return a.build(e, topLevelSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dynamic function getTopLevelEnd() {
|
||||||
|
return ignore();
|
||||||
|
}
|
||||||
|
|
||||||
public function build( e : Expr, topLevelSync = false ) {
|
public function build( e : Expr, topLevelSync = false ) {
|
||||||
if( topLevelSync ) {
|
if( topLevelSync ) {
|
||||||
return buildSync(e,null);
|
return buildSync(e,null);
|
||||||
} else {
|
} else {
|
||||||
var nothing = ignore();
|
var end = getTopLevelEnd();
|
||||||
return new Async().toCps(e, nothing, nothing);
|
return toCps(e, end, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function defineVar( v : String, mode ) {
|
||||||
|
definedVars.push({ n : v, prev : vars.get(v) });
|
||||||
|
vars.set(v, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lookupFunctions( el : Array<Expr> ) {
|
||||||
|
for( e in el )
|
||||||
|
switch( expr(e) ) {
|
||||||
|
case EFunction(_, _, name, _) if( name != null ): defineVar(name, Defined);
|
||||||
|
case EMeta("sync",_,expr(_) => EFunction(_,_,name,_)) if( name != null ): defineVar(name, ForceSync);
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function buildSync( e : Expr, exit : Expr ) : Expr {
|
function buildSync( e : Expr, exit : Expr ) : Expr {
|
||||||
switch( expr(e) ) {
|
switch( expr(e) ) {
|
||||||
case EFunction(_):
|
case EFunction(_,_,name,_):
|
||||||
return toCps(e, null, null);
|
if( name != null )
|
||||||
|
return toCps(e, null, null);
|
||||||
|
return e;
|
||||||
case EBlock(el):
|
case EBlock(el):
|
||||||
var v = saveVars();
|
var v = saveVars();
|
||||||
for( e in el )
|
lookupFunctions(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);
|
var e = block([for(e in el) buildSync(e,exit)], e);
|
||||||
restoreVars(v);
|
restoreVars(v);
|
||||||
return e;
|
return e;
|
||||||
case EMeta("async", _, e):
|
case EMeta("async", _, e):
|
||||||
return toCps(e, ignore(), ignore());
|
return toCps(e, ignore(), ignore());
|
||||||
|
case EMeta("sync", args, ef = expr(_) => EFunction(fargs, body, name, ret)):
|
||||||
|
return mk(EMeta("sync",args,mk(EFunction(fargs, buildSync(body,null), name, ret),ef)),e);
|
||||||
case EBreak if( currentBreak != null ):
|
case EBreak if( currentBreak != null ):
|
||||||
return currentBreak(e);
|
return currentBreak(e);
|
||||||
case EContinue if( currentLoop != null ):
|
case EContinue if( currentLoop != null ):
|
||||||
return block([call(currentLoop, [nullId], e), mk(EReturn(),e)],e);
|
return block([retNull(currentLoop, e), mk(EReturn(),e)],e);
|
||||||
case EFor(_), EWhile(_):
|
case EFor(_), EWhile(_):
|
||||||
var oldLoop = currentLoop, oldBreak = currentBreak;
|
var oldLoop = currentLoop, oldBreak = currentBreak;
|
||||||
currentLoop = null;
|
currentLoop = null;
|
||||||
@@ -106,14 +131,15 @@ class Async {
|
|||||||
currentBreak = oldBreak;
|
currentBreak = oldBreak;
|
||||||
return e;
|
return e;
|
||||||
case EReturn(eret) if( exit != null ):
|
case EReturn(eret) if( exit != null ):
|
||||||
return block([call(exit,[eret == null ? nullId : eret], e), mk(EReturn(),e)], e);
|
return block([eret == null ? retNull(exit, e) : call(exit,[eret], e), mk(EReturn(),e)], e);
|
||||||
default:
|
default:
|
||||||
return Tools.map(e, buildSync.bind(_, exit));
|
return Tools.map(e, buildSync.bind(_, exit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
varNames = [];
|
vars = new Map();
|
||||||
|
definedVars = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function ignore(?e) : Expr {
|
function ignore(?e) : Expr {
|
||||||
@@ -133,7 +159,9 @@ class Async {
|
|||||||
return mk(EFunction([for( a in arg ) { name : a, t : null }], e, name), e);
|
return mk(EFunction([for( a in arg ) { name : a, t : null }], e, name), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function block(arr, e) {
|
inline function block(arr:Array<Expr>, e) {
|
||||||
|
if( arr.length == 1 && expr(arr[0]).match(EBlock(_)) )
|
||||||
|
return arr[0];
|
||||||
return mk(EBlock(arr), e);
|
return mk(EBlock(arr), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,8 +177,12 @@ class Async {
|
|||||||
return mk(ECall(e, args), inf);
|
return mk(ECall(e, args), inf);
|
||||||
}
|
}
|
||||||
|
|
||||||
function retNull(e) : Expr {
|
function retNull(e:Expr,?pos) : Expr {
|
||||||
return call(e, [nullId],e);
|
switch( expr(e) ) {
|
||||||
|
case EFunction([{name:"_"}], e, _, _): return e;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return call(e, [nullId], pos == null ? e : pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeCall( ecall, args : Array<Expr>, rest : Expr, exit, sync = false ) {
|
function makeCall( ecall, args : Array<Expr>, rest : Expr, exit, sync = false ) {
|
||||||
@@ -179,7 +211,9 @@ class Async {
|
|||||||
if( !syncFlag )
|
if( !syncFlag )
|
||||||
return;
|
return;
|
||||||
switch( expr(e) ) {
|
switch( expr(e) ) {
|
||||||
case ECall(_), EFunction(_):
|
case ECall(_):
|
||||||
|
syncFlag = false;
|
||||||
|
case EFunction(_,_,name,_) if( name != null ):
|
||||||
syncFlag = false;
|
syncFlag = false;
|
||||||
case EMeta("sync" | "async", _, _):
|
case EMeta("sync" | "async", _, _):
|
||||||
// isolated from the sync part
|
// isolated from the sync part
|
||||||
@@ -189,11 +223,14 @@ class Async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function saveVars() {
|
function saveVars() {
|
||||||
return varNames.length;
|
return definedVars.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function restoreVars(k) {
|
function restoreVars(k) {
|
||||||
while( varNames.length > k ) varNames.pop();
|
while( definedVars.length > k ) {
|
||||||
|
var v = definedVars.pop();
|
||||||
|
if( v.prev == null ) vars.remove(v.n) else vars.set(v.n, v.prev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toCps( e : Expr, rest : Expr, exit : Expr ) : Expr {
|
public function toCps( e : Expr, rest : Expr, exit : Expr ) : Expr {
|
||||||
@@ -203,12 +240,7 @@ class Async {
|
|||||||
case EBlock(el):
|
case EBlock(el):
|
||||||
var el = el.copy();
|
var el = el.copy();
|
||||||
var vold = saveVars();
|
var vold = saveVars();
|
||||||
// local recursion
|
lookupFunctions(el);
|
||||||
for( e in el )
|
|
||||||
switch( expr(e) ) {
|
|
||||||
case EFunction(_, _, name, null): varNames.push(name);
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
while( el.length > 0 ) {
|
while( el.length > 0 ) {
|
||||||
var e = toCps(el.pop(), rest, exit);
|
var e = toCps(el.pop(), rest, exit);
|
||||||
rest = ignore(e);
|
rest = ignore(e);
|
||||||
@@ -218,9 +250,9 @@ class Async {
|
|||||||
case EFunction(args, body, name, t):
|
case EFunction(args, body, name, t):
|
||||||
var vold = saveVars();
|
var vold = saveVars();
|
||||||
if( name != null )
|
if( name != null )
|
||||||
varNames.push(name);
|
defineVar(name, Defined);
|
||||||
for( a in args )
|
for( a in args )
|
||||||
varNames.push(a.name);
|
defineVar(a.name, Defined);
|
||||||
args.unshift( { name : "_onEnd", t : null } );
|
args.unshift( { name : "_onEnd", t : null } );
|
||||||
var frest = ident("_onEnd",e);
|
var frest = ident("_onEnd",e);
|
||||||
var oldFun = currentFun;
|
var oldFun = currentFun;
|
||||||
@@ -241,7 +273,8 @@ class Async {
|
|||||||
var args = [for( a in args ) fun("_rest", toCps(block([a],a), ident("_rest",a), exit))];
|
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);
|
return call(ident("split",e), [rest, mk(EArrayDecl(args),e)],e);
|
||||||
case ECall(expr(_) => EIdent(i), args):
|
case ECall(expr(_) => EIdent(i), args):
|
||||||
return makeCall( ident( varNames.indexOf(i) < 0 ? "a_" + i : i,e) , args, rest, exit);
|
var mode = vars.get(i);
|
||||||
|
return makeCall( ident( mode != null ? i : "a_" + i,e) , args, rest, exit, mode == ForceSync);
|
||||||
case ECall(expr(_) => EField(e, f), args):
|
case ECall(expr(_) => EField(e, f), args):
|
||||||
return makeCall(field(e,"a_"+f,e), args, rest, exit);
|
return makeCall(field(e,"a_"+f,e), args, rest, exit);
|
||||||
case EFor(v, eit, eloop):
|
case EFor(v, eit, eloop):
|
||||||
@@ -250,7 +283,7 @@ class Async {
|
|||||||
var oldLoop = currentLoop, oldBreak = currentBreak;
|
var oldLoop = currentLoop, oldBreak = currentBreak;
|
||||||
var loop = ident("_loop" + id,e);
|
var loop = ident("_loop" + id,e);
|
||||||
currentLoop = loop;
|
currentLoop = loop;
|
||||||
currentBreak = function(inf) return block([call(rest, [nullId], inf), mk(EReturn(),inf)], inf);
|
currentBreak = function(inf) return block([retNull(rest, inf), mk(EReturn(),inf)], inf);
|
||||||
var efor = block([
|
var efor = block([
|
||||||
mk(EVar("_i" + id, call(ident("makeIterator",eit),[eit],eit)),eit),
|
mk(EVar("_i" + id, call(ident("makeIterator",eit),[eit],eit)),eit),
|
||||||
fun("_", block([
|
fun("_", block([
|
||||||
@@ -258,7 +291,7 @@ class Async {
|
|||||||
mk(EVar(v, call(field(it, "next",it), [], it)), it),
|
mk(EVar(v, call(field(it, "next",it), [], it)), it),
|
||||||
toCps(eloop, loop, exit),
|
toCps(eloop, loop, exit),
|
||||||
], it),"_loop" + id),
|
], it),"_loop" + id),
|
||||||
call(loop, [nullId], e),
|
retNull(loop, e),
|
||||||
], e);
|
], e);
|
||||||
currentLoop = oldLoop;
|
currentLoop = oldLoop;
|
||||||
currentBreak = oldBreak;
|
currentBreak = oldBreak;
|
||||||
@@ -306,18 +339,18 @@ class Async {
|
|||||||
var loop = ident("_loop" + id, cond);
|
var loop = ident("_loop" + id, cond);
|
||||||
var oldLoop = currentLoop, oldBreak = currentBreak;
|
var oldLoop = currentLoop, oldBreak = currentBreak;
|
||||||
currentLoop = loop;
|
currentLoop = loop;
|
||||||
currentBreak = function(e) return block([call(rest, [nullId], e), mk(EReturn(),e)],e);
|
currentBreak = function(e) return block([retNull(rest,e), mk(EReturn(),e)],e);
|
||||||
var ewhile = block([
|
var ewhile = block([
|
||||||
fun("_r",
|
fun("_r",
|
||||||
toCps(cond, fun("_c", mk(EIf(ident("_c", cond), toCps(ewh, loop, exit), call(rest, [nullId], cond)),cond)), exit)
|
toCps(cond, fun("_c", mk(EIf(ident("_c", cond), toCps(ewh, loop, exit), retNull(rest,cond)),cond)), exit)
|
||||||
, "_loop"+id),
|
, "_loop"+id),
|
||||||
call(loop, [nullId], cond),
|
retNull(loop, cond),
|
||||||
],e);
|
],e);
|
||||||
currentLoop = oldLoop;
|
currentLoop = oldLoop;
|
||||||
currentBreak = oldBreak;
|
currentBreak = oldBreak;
|
||||||
return ewhile;
|
return ewhile;
|
||||||
case EReturn(eret):
|
case EReturn(eret):
|
||||||
return eret == null ? call(exit, [nullId], e) : toCps(eret, exit, exit);
|
return eret == null ? retNull(exit, e) : toCps(eret, exit, exit);
|
||||||
case EObject(fields):
|
case EObject(fields):
|
||||||
var id = "_o" + uid++;
|
var id = "_o" + uid++;
|
||||||
var rest = call(rest, [ident(id,e)], e);
|
var rest = call(rest, [ident(id,e)], e);
|
||||||
@@ -353,10 +386,10 @@ class Async {
|
|||||||
return toCps(earr, fun(id1, toCps(eindex, fun(id2, call(rest, [mk(EArray(ident(id1,e), ident(id2,e)),e)], e)), exit)), exit);
|
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):
|
case EVar(v, t, ev):
|
||||||
if( ev == null )
|
if( ev == null )
|
||||||
return block([e, call(rest, [nullId],e)], e);
|
return block([e, retNull(rest, e)], e);
|
||||||
return block([
|
return block([
|
||||||
mk(EVar(v, t),e),
|
mk(EVar(v, t),e),
|
||||||
toCps(ev, fun("_r", block([binop("=", ident(v,e), ident("_r",e), e), call(rest,[nullId],e)], e)), exit),
|
toCps(ev, fun("_r", block([binop("=", ident(v,e), ident("_r",e), e), retNull(rest,e)], e)), exit),
|
||||||
],e);
|
],e);
|
||||||
case EConst(_), EIdent(_), EUnop(_), EField(_):
|
case EConst(_), EIdent(_), EUnop(_), EField(_):
|
||||||
return call(rest, [e], e);
|
return call(rest, [e], e);
|
||||||
@@ -375,12 +408,14 @@ class Async {
|
|||||||
return currentBreak(e);
|
return currentBreak(e);
|
||||||
case EContinue:
|
case EContinue:
|
||||||
if( currentLoop == null ) throw "Continue outside loop";
|
if( currentLoop == null ) throw "Continue outside loop";
|
||||||
return block([call(currentLoop, [nullId], e), mk(EReturn(),e)], e);
|
return block([retNull(currentLoop, e), mk(EReturn(),e)], e);
|
||||||
case ESwitch(v, cases, def):
|
case ESwitch(v, cases, def):
|
||||||
var cases = [for( c in cases ) { values : c.values, expr : toCps(c.expr, rest, exit) } ];
|
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 );
|
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):
|
case EThrow(v):
|
||||||
return toCps(v, mk(EFunction([ { name : "_v", t : null } ], mk(EThrow(v),v)), v), exit);
|
return toCps(v, mk(EFunction([ { name : "_v", t : null } ], mk(EThrow(v),v)), v), exit);
|
||||||
|
case EMeta(name,_,e) if( name.charCodeAt(0) == ":".code ): // ignore custom ":" metadata
|
||||||
|
return toCps(e, rest, exit);
|
||||||
//case EDoWhile(_), ETry(_), ECall(_):
|
//case EDoWhile(_), ETry(_), ECall(_):
|
||||||
default:
|
default:
|
||||||
throw "Unsupported async expression " + Printer.toString(e);
|
throw "Unsupported async expression " + Printer.toString(e);
|
||||||
|
|||||||
+10
-5
@@ -72,10 +72,7 @@ class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doEncodeInt(v: Int) {
|
function doEncodeInt(v: Int) {
|
||||||
bout.addByte(v & 0xFF);
|
bout.addInt32(v);
|
||||||
bout.addByte((v >> 8) & 0xFF);
|
|
||||||
bout.addByte((v >> 16) & 0xFF);
|
|
||||||
bout.addByte(v >>> 24);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doEncodeConst( c : Const ) {
|
function doEncodeConst( c : Const ) {
|
||||||
@@ -107,7 +104,7 @@ class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doDecodeInt() {
|
function doDecodeInt() {
|
||||||
var i = bin.get(pin) | (bin.get(pin+1) << 8) | (bin.get(pin+2) << 16) | (bin.get(pin+3) << 24);
|
var i = bin.getInt32(pin);
|
||||||
pin += 4;
|
pin += 4;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@@ -249,11 +246,17 @@ class Bytes {
|
|||||||
bout.addByte(args == null ? 0 : args.length + 1);
|
bout.addByte(args == null ? 0 : args.length + 1);
|
||||||
if( args != null ) for( e in args ) doEncode(e);
|
if( args != null ) for( e in args ) doEncode(e);
|
||||||
doEncode(e);
|
doEncode(e);
|
||||||
|
case ECheckType(e,_):
|
||||||
|
doEncode(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doDecode() : Expr {
|
function doDecode() : Expr {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
|
if (bin.get(pin) == 255) {
|
||||||
|
pin++;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
var origin = doDecodeString();
|
var origin = doDecodeString();
|
||||||
var line = doDecodeInt();
|
var line = doDecodeInt();
|
||||||
return { e : _doDecode(), pmin : 0, pmax : 0, origin : origin, line : line };
|
return { e : _doDecode(), pmin : 0, pmax : 0, origin : origin, line : line };
|
||||||
@@ -373,6 +376,8 @@ class Bytes {
|
|||||||
var count = bin.get(pin++);
|
var count = bin.get(pin++);
|
||||||
var args = count == 0 ? null : [for( i in 0...count - 1 ) doDecode()];
|
var args = count == 0 ? null : [for( i in 0...count - 1 ) doDecode()];
|
||||||
EMeta(name, args, doDecode());
|
EMeta(name, args, doDecode());
|
||||||
|
case 26:
|
||||||
|
ECheckType(doDecode(), CTPath(["Void"]));
|
||||||
case 255:
|
case 255:
|
||||||
null;
|
null;
|
||||||
default:
|
default:
|
||||||
|
|||||||
+1184
File diff suppressed because it is too large
Load Diff
@@ -40,6 +40,7 @@ typedef Expr = {
|
|||||||
}
|
}
|
||||||
enum ExprDef {
|
enum ExprDef {
|
||||||
#else
|
#else
|
||||||
|
typedef ExprDef = Expr;
|
||||||
enum Expr {
|
enum Expr {
|
||||||
#end
|
#end
|
||||||
EConst( c : Const );
|
EConst( c : Const );
|
||||||
@@ -68,6 +69,7 @@ enum Expr {
|
|||||||
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr);
|
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr);
|
||||||
EDoWhile( cond : Expr, e : Expr);
|
EDoWhile( cond : Expr, e : Expr);
|
||||||
EMeta( name : String, args : Array<Expr>, e : Expr );
|
EMeta( name : String, args : Array<Expr>, e : Expr );
|
||||||
|
ECheckType( e : Expr, t : CType );
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||||
@@ -79,6 +81,8 @@ enum CType {
|
|||||||
CTFun( args : Array<CType>, ret : CType );
|
CTFun( args : Array<CType>, ret : CType );
|
||||||
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
|
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
|
||||||
CTParent( t : CType );
|
CTParent( t : CType );
|
||||||
|
CTOpt( t : CType );
|
||||||
|
CTNamed( n : String, t : CType );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
|
|||||||
+20
-18
@@ -52,13 +52,22 @@ class Interp {
|
|||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
#if haxe3
|
#if haxe3
|
||||||
variables = new Map<String,Dynamic>();
|
|
||||||
locals = new Map();
|
locals = new Map();
|
||||||
#else
|
#else
|
||||||
variables = new Hash();
|
|
||||||
locals = new Hash();
|
locals = new Hash();
|
||||||
#end
|
#end
|
||||||
declared = new Array();
|
declared = new Array();
|
||||||
|
resetVariables();
|
||||||
|
initOps();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resetVariables(){
|
||||||
|
#if haxe3
|
||||||
|
variables = new Map<String,Dynamic>();
|
||||||
|
#else
|
||||||
|
variables = new Hash();
|
||||||
|
#end
|
||||||
|
|
||||||
variables.set("null",null);
|
variables.set("null",null);
|
||||||
variables.set("true",true);
|
variables.set("true",true);
|
||||||
variables.set("false",false);
|
variables.set("false",false);
|
||||||
@@ -68,7 +77,6 @@ class Interp {
|
|||||||
if( el.length > 0 ) inf.customParams = el;
|
if( el.length > 0 ) inf.customParams = el;
|
||||||
haxe.Log.trace(Std.string(v), inf);
|
haxe.Log.trace(Std.string(v), inf);
|
||||||
}));
|
}));
|
||||||
initOps();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function posInfos(): PosInfos {
|
public function posInfos(): PosInfos {
|
||||||
@@ -122,7 +130,7 @@ class Interp {
|
|||||||
|
|
||||||
function assign( e1 : Expr, e2 : Expr ) : Dynamic {
|
function assign( e1 : Expr, e2 : Expr ) : Dynamic {
|
||||||
var v = expr(e2);
|
var v = expr(e2);
|
||||||
switch( edef(e1) ) {
|
switch( Tools.expr(e1) ) {
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
var l = locals.get(id);
|
var l = locals.get(id);
|
||||||
if( l == null )
|
if( l == null )
|
||||||
@@ -154,7 +162,7 @@ class Interp {
|
|||||||
|
|
||||||
function evalAssignOp(op,fop,e1,e2) : Dynamic {
|
function evalAssignOp(op,fop,e1,e2) : Dynamic {
|
||||||
var v;
|
var v;
|
||||||
switch( edef(e1) ) {
|
switch( Tools.expr(e1) ) {
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
var l = locals.get(id);
|
var l = locals.get(id);
|
||||||
v = fop(expr(e1),expr(e2));
|
v = fop(expr(e1),expr(e2));
|
||||||
@@ -280,14 +288,6 @@ class Interp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function edef( e : Expr ) {
|
|
||||||
#if hscriptPos
|
|
||||||
return e.e;
|
|
||||||
#else
|
|
||||||
return e;
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
|
|
||||||
inline function error(e : #if hscriptPos ErrorDef #else Error #end, rethrow=false ) : Dynamic {
|
inline function error(e : #if hscriptPos ErrorDef #else Error #end, rethrow=false ) : Dynamic {
|
||||||
#if hscriptPos var e = new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line); #end
|
#if hscriptPos var e = new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line); #end
|
||||||
if( rethrow ) this.rethrow(e) else throw e;
|
if( rethrow ) this.rethrow(e) else throw e;
|
||||||
@@ -372,7 +372,7 @@ class Interp {
|
|||||||
for( p in params )
|
for( p in params )
|
||||||
args.push(expr(p));
|
args.push(expr(p));
|
||||||
|
|
||||||
switch( edef(e) ) {
|
switch( Tools.expr(e) ) {
|
||||||
case EField(e,f):
|
case EField(e,f):
|
||||||
var obj = expr(e);
|
var obj = expr(e);
|
||||||
if( obj == null ) error(EInvalidAccess(f));
|
if( obj == null ) error(EInvalidAccess(f));
|
||||||
@@ -408,11 +408,11 @@ class Interp {
|
|||||||
else
|
else
|
||||||
minParams++;
|
minParams++;
|
||||||
var f = function(args:Array<Dynamic>) {
|
var f = function(args:Array<Dynamic>) {
|
||||||
if( args.length != params.length ) {
|
if( ( (args == null) ? 0 : args.length ) != params.length ) {
|
||||||
if( args.length < minParams ) {
|
if( args.length < minParams ) {
|
||||||
var str = "Invalid number of parameters. Got " + args.length + ", required " + minParams;
|
var str = "Invalid number of parameters. Got " + args.length + ", required " + minParams;
|
||||||
if( name != null ) str += " for function '" + name+"'";
|
if( name != null ) str += " for function '" + name+"'";
|
||||||
throw str;
|
error(ECustom(str));
|
||||||
}
|
}
|
||||||
// make sure mandatory args are forced
|
// make sure mandatory args are forced
|
||||||
var args2 = [];
|
var args2 = [];
|
||||||
@@ -468,7 +468,7 @@ class Interp {
|
|||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
case EArrayDecl(arr):
|
case EArrayDecl(arr):
|
||||||
if (arr.length > 0 && edef(arr[0]).match(EBinop("=>", _))) {
|
if (arr.length > 0 && Tools.expr(arr[0]).match(EBinop("=>", _))) {
|
||||||
var isAllString:Bool = true;
|
var isAllString:Bool = true;
|
||||||
var isAllInt:Bool = true;
|
var isAllInt:Bool = true;
|
||||||
var isAllObject:Bool = true;
|
var isAllObject:Bool = true;
|
||||||
@@ -476,7 +476,7 @@ class Interp {
|
|||||||
var keys:Array<Dynamic> = [];
|
var keys:Array<Dynamic> = [];
|
||||||
var values:Array<Dynamic> = [];
|
var values:Array<Dynamic> = [];
|
||||||
for (e in arr) {
|
for (e in arr) {
|
||||||
switch(edef(e)) {
|
switch(Tools.expr(e)) {
|
||||||
case EBinop("=>", eKey, eValue): {
|
case EBinop("=>", eKey, eValue): {
|
||||||
var key:Dynamic = expr(eKey);
|
var key:Dynamic = expr(eKey);
|
||||||
var value:Dynamic = expr(eValue);
|
var value:Dynamic = expr(eValue);
|
||||||
@@ -574,6 +574,8 @@ class Interp {
|
|||||||
return val;
|
return val;
|
||||||
case EMeta(_, _, e):
|
case EMeta(_, _, e):
|
||||||
return expr(e);
|
return expr(e);
|
||||||
|
case ECheckType(e,_):
|
||||||
|
return expr(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-1
@@ -113,6 +113,7 @@ class Macro {
|
|||||||
|
|
||||||
function convertType( t : Expr.CType ) : ComplexType {
|
function convertType( t : Expr.CType ) : ComplexType {
|
||||||
return switch( t ) {
|
return switch( t ) {
|
||||||
|
case CTOpt(t): TOptional(convertType(t));
|
||||||
case CTPath(pack, args):
|
case CTPath(pack, args):
|
||||||
var params = [];
|
var params = [];
|
||||||
if( args != null )
|
if( args != null )
|
||||||
@@ -127,6 +128,12 @@ class Macro {
|
|||||||
case CTParent(t): TParent(convertType(t));
|
case CTParent(t): TParent(convertType(t));
|
||||||
case CTFun(args, ret):
|
case CTFun(args, ret):
|
||||||
TFunction(map(args,convertType), convertType(ret));
|
TFunction(map(args,convertType), convertType(ret));
|
||||||
|
case CTNamed(name, convertType(_) => ct):
|
||||||
|
#if (haxe_ver >= 4)
|
||||||
|
TNamed(name, ct);
|
||||||
|
#else
|
||||||
|
ct;
|
||||||
|
#end
|
||||||
case CTAnon(fields):
|
case CTAnon(fields):
|
||||||
var tf = [];
|
var tf = [];
|
||||||
for( f in fields ) {
|
for( f in fields ) {
|
||||||
@@ -207,7 +214,7 @@ class Macro {
|
|||||||
opt : false,
|
opt : false,
|
||||||
value : null,
|
value : null,
|
||||||
});
|
});
|
||||||
EFunction(name, {
|
EFunction(#if haxe4 FNamed(name,false) #else name #end, {
|
||||||
params : [],
|
params : [],
|
||||||
args : targs,
|
args : targs,
|
||||||
expr : convert(e),
|
expr : convert(e),
|
||||||
@@ -238,6 +245,8 @@ class Macro {
|
|||||||
case EMeta(m, params, esub):
|
case EMeta(m, params, esub):
|
||||||
var mpos = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
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));
|
EMeta({ name : m, params : params == null ? [] : [for( p in params ) convert(p)], pos : mpos }, convert(esub));
|
||||||
|
case ECheckType(e, t):
|
||||||
|
ECheckType(convert(e), convertType(t));
|
||||||
}, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end }
|
}, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+205
-93
@@ -78,8 +78,15 @@ class Parser {
|
|||||||
**/
|
**/
|
||||||
public var allowMetadata : Bool;
|
public var allowMetadata : Bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
resume from parsing errors (when parsing incomplete code, during completion for example)
|
||||||
|
**/
|
||||||
|
public var resumeErrors : Bool;
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
var input : haxe.io.Input;
|
var input : String;
|
||||||
|
var readPos : Int;
|
||||||
|
|
||||||
var char : Int;
|
var char : Int;
|
||||||
var ops : Array<Bool>;
|
var ops : Array<Bool>;
|
||||||
var idents : Array<Bool>;
|
var idents : Array<Bool>;
|
||||||
@@ -87,7 +94,6 @@ class Parser {
|
|||||||
|
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
var origin : String;
|
var origin : String;
|
||||||
var readPos : Int;
|
|
||||||
var tokenMin : Int;
|
var tokenMin : Int;
|
||||||
var tokenMax : Int;
|
var tokenMax : Int;
|
||||||
var oldTokenMin : Int;
|
var oldTokenMin : Int;
|
||||||
@@ -95,7 +101,6 @@ class Parser {
|
|||||||
var tokens : List<{ min : Int, max : Int, t : Token }>;
|
var tokens : List<{ min : Int, max : Int, t : Token }>;
|
||||||
#else
|
#else
|
||||||
static inline var p1 = 0;
|
static inline var p1 = 0;
|
||||||
static inline var readPos = 0;
|
|
||||||
static inline var tokenMin = 0;
|
static inline var tokenMin = 0;
|
||||||
static inline var tokenMax = 0;
|
static inline var tokenMax = 0;
|
||||||
#if haxe3
|
#if haxe3
|
||||||
@@ -142,6 +147,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public inline function error( err, pmin, pmax ) {
|
public inline function error( err, pmin, pmax ) {
|
||||||
|
if( !resumeErrors )
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
throw new Error(err, pmin, pmax, origin, line);
|
throw new Error(err, pmin, pmax, origin, line);
|
||||||
#else
|
#else
|
||||||
@@ -150,7 +156,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function invalidChar(c) {
|
public function invalidChar(c) {
|
||||||
error(EInvalidChar(c), readPos, readPos);
|
error(EInvalidChar(c), readPos-1, readPos-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initParser( origin ) {
|
function initParser( origin ) {
|
||||||
@@ -178,12 +184,9 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function parseString( s : String, ?origin : String = "hscript" ) {
|
public function parseString( s : String, ?origin : String = "hscript" ) {
|
||||||
return parse( new haxe.io.StringInput(s), origin );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function parse( s : haxe.io.Input, ?origin : String = "hscript" ) {
|
|
||||||
initParser(origin);
|
initParser(origin);
|
||||||
input = s;
|
input = s;
|
||||||
|
readPos = 0;
|
||||||
var a = new Array();
|
var a = new Array();
|
||||||
while( true ) {
|
while( true ) {
|
||||||
var tk = token();
|
var tk = token();
|
||||||
@@ -247,7 +250,7 @@ class Parser {
|
|||||||
|
|
||||||
inline function pmin(e:Expr) {
|
inline function pmin(e:Expr) {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return e.pmin;
|
return e == null ? 0 : e.pmin;
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#end
|
#end
|
||||||
@@ -255,7 +258,7 @@ class Parser {
|
|||||||
|
|
||||||
inline function pmax(e:Expr) {
|
inline function pmax(e:Expr) {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return e.pmax;
|
return e == null ? 0 : e.pmax;
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#end
|
#end
|
||||||
@@ -273,6 +276,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isBlock(e) {
|
function isBlock(e) {
|
||||||
|
if( e == null ) return false;
|
||||||
return switch( expr(e) ) {
|
return switch( expr(e) ) {
|
||||||
case EBlock(_), EObject(_), ESwitch(_): true;
|
case EBlock(_), EObject(_), ESwitch(_): true;
|
||||||
case EFunction(_,e,_,_): isBlock(e);
|
case EFunction(_,e,_,_): isBlock(e);
|
||||||
@@ -296,7 +300,7 @@ class Parser {
|
|||||||
|
|
||||||
var tk = token();
|
var tk = token();
|
||||||
// this is a hack to support var a,b,c; with a single EVar
|
// this is a hack to support var a,b,c; with a single EVar
|
||||||
while( tk == TComma && expr(e).match(EVar(_)) ) {
|
while( tk == TComma && e != null && expr(e).match(EVar(_)) ) {
|
||||||
e = parseStructure("var"); // next variable
|
e = parseStructure("var"); // next variable
|
||||||
exprs.push(e);
|
exprs.push(e);
|
||||||
tk = token();
|
tk = token();
|
||||||
@@ -329,6 +333,7 @@ class Parser {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
ensure(TDoubleDot);
|
ensure(TDoubleDot);
|
||||||
fl.push({ name : id, e : parseExpr() });
|
fl.push({ name : id, e : parseExpr() });
|
||||||
@@ -359,8 +364,31 @@ class Parser {
|
|||||||
return parseExprNext(mk(EConst(c)));
|
return parseExprNext(mk(EConst(c)));
|
||||||
case TPOpen:
|
case TPOpen:
|
||||||
var e = parseExpr();
|
var e = parseExpr();
|
||||||
ensure(TPClose);
|
tk = token();
|
||||||
return parseExprNext(mk(EParent(e),p1,tokenMax));
|
switch( tk ) {
|
||||||
|
case TPClose:
|
||||||
|
return parseExprNext(mk(EParent(e),p1,tokenMax));
|
||||||
|
case TDoubleDot:
|
||||||
|
var t = parseType();
|
||||||
|
tk = token();
|
||||||
|
switch( tk ) {
|
||||||
|
case TPClose:
|
||||||
|
return parseExprNext(mk(ECheckType(e,t),p1,tokenMax));
|
||||||
|
case TComma:
|
||||||
|
switch( expr(e) ) {
|
||||||
|
case EIdent(v): return parseLambda([{ name : v, t : t }], pmin(e));
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
case TComma:
|
||||||
|
switch( expr(e) ) {
|
||||||
|
case EIdent(v): return parseLambda([{name:v}], pmin(e));
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return unexpected(tk);
|
||||||
case TBrOpen:
|
case TBrOpen:
|
||||||
tk = token();
|
tk = token();
|
||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
@@ -399,7 +427,7 @@ class Parser {
|
|||||||
while( true ) {
|
while( true ) {
|
||||||
parseFullExpr(a);
|
parseFullExpr(a);
|
||||||
tk = token();
|
tk = token();
|
||||||
if( tk == TBrClose )
|
if( tk == TBrClose || (resumeErrors && tk == TEof) )
|
||||||
break;
|
break;
|
||||||
push(tk);
|
push(tk);
|
||||||
}
|
}
|
||||||
@@ -408,7 +436,7 @@ class Parser {
|
|||||||
if( unops.exists(op) ) {
|
if( unops.exists(op) ) {
|
||||||
var start = tokenMin;
|
var start = tokenMin;
|
||||||
var e = parseExpr();
|
var e = parseExpr();
|
||||||
if( op == "-" )
|
if( op == "-" && e != null )
|
||||||
switch( expr(e) ) {
|
switch( expr(e) ) {
|
||||||
case EConst(CInt(i)):
|
case EConst(CInt(i)):
|
||||||
return mk(EConst(CInt(-i)), start, pmax(e));
|
return mk(EConst(CInt(-i)), start, pmax(e));
|
||||||
@@ -422,14 +450,14 @@ class Parser {
|
|||||||
case TBkOpen:
|
case TBkOpen:
|
||||||
var a = new Array();
|
var a = new Array();
|
||||||
tk = token();
|
tk = token();
|
||||||
while( tk != TBkClose ) {
|
while( tk != TBkClose && (!resumeErrors || tk != TEof) ) {
|
||||||
push(tk);
|
push(tk);
|
||||||
a.push(parseExpr());
|
a.push(parseExpr());
|
||||||
tk = token();
|
tk = token();
|
||||||
if( tk == TComma )
|
if( tk == TComma )
|
||||||
tk = token();
|
tk = token();
|
||||||
}
|
}
|
||||||
if( a.length == 1 )
|
if( a.length == 1 && a[0] != null )
|
||||||
switch( expr(a[0]) ) {
|
switch( expr(a[0]) ) {
|
||||||
case EFor(_), EWhile(_), EDoWhile(_):
|
case EFor(_), EWhile(_), EDoWhile(_):
|
||||||
var tmp = "__a_" + (uid++);
|
var tmp = "__a_" + (uid++);
|
||||||
@@ -450,6 +478,26 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseLambda( args : Array<Argument>, pmin ) {
|
||||||
|
while( true ) {
|
||||||
|
var id = getIdent();
|
||||||
|
var t = maybe(TDoubleDot) ? parseType() : null;
|
||||||
|
args.push({ name : id, t : t });
|
||||||
|
var tk = token();
|
||||||
|
switch( tk ) {
|
||||||
|
case TComma:
|
||||||
|
case TPClose:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unexpected(tk);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ensureToken(TOp("->"));
|
||||||
|
var eret = parseExpr();
|
||||||
|
return mk(EFunction(args, mk(EReturn(eret),pmin)), pmin);
|
||||||
|
}
|
||||||
|
|
||||||
function parseMetaArgs() {
|
function parseMetaArgs() {
|
||||||
var tk = token();
|
var tk = token();
|
||||||
if( tk != TPOpen ) {
|
if( tk != TPOpen ) {
|
||||||
@@ -475,6 +523,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapCompr( tmp : String, e : Expr ) {
|
function mapCompr( tmp : String, e : Expr ) {
|
||||||
|
if( e == null ) return null;
|
||||||
var edef = switch( expr(e) ) {
|
var edef = switch( expr(e) ) {
|
||||||
case EFor(v, it, e2):
|
case EFor(v, it, e2):
|
||||||
EFor(v, it, mapCompr(tmp, e2));
|
EFor(v, it, mapCompr(tmp, e2));
|
||||||
@@ -495,6 +544,8 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function makeUnop( op, e ) {
|
function makeUnop( op, e ) {
|
||||||
|
if( e == null && resumeErrors )
|
||||||
|
return null;
|
||||||
return switch( expr(e) ) {
|
return switch( expr(e) ) {
|
||||||
case EBinop(bop, e1, e2): mk(EBinop(bop, makeUnop(op, e1), e2), pmin(e1), pmax(e2));
|
case EBinop(bop, e1, e2): mk(EBinop(bop, makeUnop(op, e1), e2), pmin(e1), pmax(e2));
|
||||||
case ETernary(e1, e2, e3): mk(ETernary(makeUnop(op, e1), e2, e3), pmin(e1), pmax(e3));
|
case ETernary(e1, e2, e3): mk(ETernary(makeUnop(op, e1), e2, e3), pmin(e1), pmax(e3));
|
||||||
@@ -503,6 +554,8 @@ class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function makeBinop( op, e1, e ) {
|
function makeBinop( op, e1, e ) {
|
||||||
|
if( e == null && resumeErrors )
|
||||||
|
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
||||||
return switch( expr(e) ) {
|
return switch( expr(e) ) {
|
||||||
case EBinop(op2,e2,e3):
|
case EBinop(op2,e2,e3):
|
||||||
if( opPriority.get(op) <= opPriority.get(op2) && !opRightAssoc.exists(op) )
|
if( opPriority.get(op) <= opPriority.get(op2) && !opRightAssoc.exists(op) )
|
||||||
@@ -602,16 +655,16 @@ class Parser {
|
|||||||
case "new":
|
case "new":
|
||||||
var a = new Array();
|
var a = new Array();
|
||||||
a.push(getIdent());
|
a.push(getIdent());
|
||||||
var next = true;
|
while( true ) {
|
||||||
while( next ) {
|
|
||||||
var tk = token();
|
var tk = token();
|
||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TDot:
|
case TDot:
|
||||||
a.push(getIdent());
|
a.push(getIdent());
|
||||||
case TPOpen:
|
case TPOpen:
|
||||||
next = false;
|
break;
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var args = parseExprList(TPClose);
|
var args = parseExprList(TPClose);
|
||||||
@@ -654,6 +707,7 @@ class Parser {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var exprs = [];
|
var exprs = [];
|
||||||
@@ -663,6 +717,8 @@ class Parser {
|
|||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TId("case"), TId("default"), TBrClose:
|
case TId("case"), TId("default"), TBrClose:
|
||||||
break;
|
break;
|
||||||
|
case TEof if( resumeErrors ):
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
parseFullExpr(exprs);
|
parseFullExpr(exprs);
|
||||||
}
|
}
|
||||||
@@ -683,6 +739,8 @@ class Parser {
|
|||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TId("case"), TId("default"), TBrClose:
|
case TId("case"), TId("default"), TBrClose:
|
||||||
break;
|
break;
|
||||||
|
case TEof if( resumeErrors ):
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
parseFullExpr(exprs);
|
parseFullExpr(exprs);
|
||||||
}
|
}
|
||||||
@@ -697,6 +755,7 @@ class Parser {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mk(ESwitch(e, cases, def), p1, tokenMax);
|
mk(ESwitch(e, cases, def), p1, tokenMax);
|
||||||
@@ -709,6 +768,21 @@ class Parser {
|
|||||||
var tk = token();
|
var tk = token();
|
||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TOp(op):
|
case TOp(op):
|
||||||
|
|
||||||
|
if( op == "->" ) {
|
||||||
|
// single arg reinterpretation of `f -> e` , `(f) -> e` and `(f:T) -> e`
|
||||||
|
switch( expr(e1) ) {
|
||||||
|
case EIdent(i), EParent(expr(_) => EIdent(i)):
|
||||||
|
var eret = parseExpr();
|
||||||
|
return mk(EFunction([{ name : i }], mk(EReturn(eret),pmin(eret))), pmin(e1));
|
||||||
|
case ECheckType(expr(_) => EIdent(i), t):
|
||||||
|
var eret = parseExpr();
|
||||||
|
return mk(EFunction([{ name : i, t : t }], mk(EReturn(eret),pmin(eret))), pmin(e1));
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
unexpected(tk);
|
||||||
|
}
|
||||||
|
|
||||||
if( unops.get(op) ) {
|
if( unops.get(op) ) {
|
||||||
if( isBlock(e1) || switch(expr(e1)) { case EParent(_): true; default: false; } ) {
|
if( isBlock(e1) || switch(expr(e1)) { case EParent(_): true; default: false; } ) {
|
||||||
push(tk);
|
push(tk);
|
||||||
@@ -737,8 +811,7 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseFunctionDecl() {
|
function parseFunctionArgs() {
|
||||||
ensure(TPOpen);
|
|
||||||
var args = new Array();
|
var args = new Array();
|
||||||
var tk = token();
|
var tk = token();
|
||||||
if( tk != TPClose ) {
|
if( tk != TPClose ) {
|
||||||
@@ -753,7 +826,9 @@ class Parser {
|
|||||||
}
|
}
|
||||||
switch( tk ) {
|
switch( tk ) {
|
||||||
case TId(id): name = id;
|
case TId(id): name = id;
|
||||||
default: unexpected(tk);
|
default:
|
||||||
|
unexpected(tk);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
var arg : Argument = { name : name };
|
var arg : Argument = { name : name };
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
@@ -775,9 +850,15 @@ class Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFunctionDecl() {
|
||||||
|
ensure(TPOpen);
|
||||||
|
var args = parseFunctionArgs();
|
||||||
var ret = null;
|
var ret = null;
|
||||||
if( allowTypes ) {
|
if( allowTypes ) {
|
||||||
tk = token();
|
var tk = token();
|
||||||
if( tk != TDoubleDot )
|
if( tk != TDoubleDot )
|
||||||
push(tk);
|
push(tk);
|
||||||
else
|
else
|
||||||
@@ -829,6 +910,7 @@ class Parser {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
unexpected(t);
|
unexpected(t);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
push(t);
|
push(t);
|
||||||
@@ -837,9 +919,53 @@ class Parser {
|
|||||||
}
|
}
|
||||||
return parseTypeNext(CTPath(path, params));
|
return parseTypeNext(CTPath(path, params));
|
||||||
case TPOpen:
|
case TPOpen:
|
||||||
var t = parseType();
|
var a = token(),
|
||||||
ensure(TPClose);
|
b = token();
|
||||||
return parseTypeNext(CTParent(t));
|
|
||||||
|
push(b);
|
||||||
|
push(a);
|
||||||
|
|
||||||
|
function withReturn(args) {
|
||||||
|
switch token() { // I think it wouldn't hurt if ensure used enumEq
|
||||||
|
case TOp('->'):
|
||||||
|
case t: unexpected(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CTFun(args, parseType());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch [a, b] {
|
||||||
|
case [TPClose, _] | [TId(_), TDoubleDot]:
|
||||||
|
|
||||||
|
var args = [for (arg in parseFunctionArgs()) {
|
||||||
|
switch arg.value {
|
||||||
|
case null:
|
||||||
|
case v:
|
||||||
|
error(ECustom('Default values not allowed in function types'), #if hscriptPos v.pmin, v.pmax #else 0, 0 #end);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTNamed(arg.name, if (arg.opt) CTOpt(arg.t) else arg.t);
|
||||||
|
}];
|
||||||
|
|
||||||
|
return withReturn(args);
|
||||||
|
default:
|
||||||
|
|
||||||
|
var t = parseType();
|
||||||
|
return switch token() {
|
||||||
|
case TComma:
|
||||||
|
var args = [t];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
args.push(parseType());
|
||||||
|
if (!maybe(TComma)) break;
|
||||||
|
}
|
||||||
|
ensure(TPClose);
|
||||||
|
withReturn(args);
|
||||||
|
case TPClose:
|
||||||
|
parseTypeNext(CTParent(t));
|
||||||
|
case t: unexpected(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
case TBrOpen:
|
case TBrOpen:
|
||||||
var fields = [];
|
var fields = [];
|
||||||
var meta = null;
|
var meta = null;
|
||||||
@@ -867,6 +993,7 @@ class Parser {
|
|||||||
meta.push({ name : name, params : parseMetaArgs() });
|
meta.push({ name : name, params : parseMetaArgs() });
|
||||||
default:
|
default:
|
||||||
unexpected(t);
|
unexpected(t);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parseTypeNext(CTAnon(fields));
|
return parseTypeNext(CTAnon(fields));
|
||||||
@@ -911,6 +1038,7 @@ class Parser {
|
|||||||
default:
|
default:
|
||||||
if( tk == etk ) break;
|
if( tk == etk ) break;
|
||||||
unexpected(tk);
|
unexpected(tk);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
@@ -920,7 +1048,8 @@ class Parser {
|
|||||||
|
|
||||||
public function parseModule( content : String, ?origin : String = "hscript" ) {
|
public function parseModule( content : String, ?origin : String = "hscript" ) {
|
||||||
initParser(origin);
|
initParser(origin);
|
||||||
this.input = new haxe.io.StringInput(content);
|
input = content;
|
||||||
|
readPos = 0;
|
||||||
allowTypes = true;
|
allowTypes = true;
|
||||||
allowMetadata = true;
|
allowMetadata = true;
|
||||||
var decls = [];
|
var decls = [];
|
||||||
@@ -1113,6 +1242,7 @@ class Parser {
|
|||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
unexpected(TId(id));
|
unexpected(TId(id));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -1120,20 +1250,13 @@ class Parser {
|
|||||||
|
|
||||||
// ------------------------ lexing -------------------------------
|
// ------------------------ lexing -------------------------------
|
||||||
|
|
||||||
inline function incPos() {
|
inline function readChar() {
|
||||||
#if hscriptPos
|
return StringTools.fastCodeAt(input, readPos++);
|
||||||
readPos++;
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
|
|
||||||
function readChar() {
|
|
||||||
incPos();
|
|
||||||
return try input.readByte() catch( e : Dynamic ) 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function readString( until ) {
|
function readString( until ) {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
var b = new haxe.io.BytesOutput();
|
var b = new StringBuf();
|
||||||
var esc = false;
|
var esc = false;
|
||||||
var old = line;
|
var old = line;
|
||||||
var s = input;
|
var s = input;
|
||||||
@@ -1141,38 +1264,26 @@ class Parser {
|
|||||||
var p1 = readPos - 1;
|
var p1 = readPos - 1;
|
||||||
#end
|
#end
|
||||||
while( true ) {
|
while( true ) {
|
||||||
try {
|
var c = readChar();
|
||||||
incPos();
|
if( StringTools.isEof(c) ) {
|
||||||
c = s.readByte();
|
|
||||||
} catch( e : Dynamic ) {
|
|
||||||
line = old;
|
line = old;
|
||||||
error(EUnterminatedString, p1, p1);
|
error(EUnterminatedString, p1, p1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if( esc ) {
|
if( esc ) {
|
||||||
esc = false;
|
esc = false;
|
||||||
switch( c ) {
|
switch( c ) {
|
||||||
case 'n'.code: b.writeByte(10);
|
case 'n'.code: b.addChar('\n'.code);
|
||||||
case 'r'.code: b.writeByte(13);
|
case 'r'.code: b.addChar('\r'.code);
|
||||||
case 't'.code: b.writeByte(9);
|
case 't'.code: b.addChar('\t'.code);
|
||||||
case "'".code, '"'.code, '\\'.code: b.writeByte(c);
|
case "'".code, '"'.code, '\\'.code: b.addChar(c);
|
||||||
case '/'.code: if( allowJSON ) b.writeByte(c) else invalidChar(c);
|
case '/'.code: if( allowJSON ) b.addChar(c) else invalidChar(c);
|
||||||
case "u".code:
|
case "u".code:
|
||||||
if( !allowJSON ) invalidChar(c);
|
if( !allowJSON ) invalidChar(c);
|
||||||
var code = null;
|
|
||||||
try {
|
|
||||||
incPos();
|
|
||||||
incPos();
|
|
||||||
incPos();
|
|
||||||
incPos();
|
|
||||||
code = s.readString(4);
|
|
||||||
} catch( e : Dynamic ) {
|
|
||||||
line = old;
|
|
||||||
error(EUnterminatedString, p1, p1);
|
|
||||||
}
|
|
||||||
var k = 0;
|
var k = 0;
|
||||||
for( i in 0...4 ) {
|
for( i in 0...4 ) {
|
||||||
k <<= 4;
|
k <<= 4;
|
||||||
var char = code.charCodeAt(i);
|
var char = readChar();
|
||||||
switch( char ) {
|
switch( char ) {
|
||||||
case 48,49,50,51,52,53,54,55,56,57: // 0-9
|
case 48,49,50,51,52,53,54,55,56,57: // 0-9
|
||||||
k += char - 48;
|
k += char - 48;
|
||||||
@@ -1181,20 +1292,14 @@ class Parser {
|
|||||||
case 97,98,99,100,101,102: // a-f
|
case 97,98,99,100,101,102: // a-f
|
||||||
k += char - 87;
|
k += char - 87;
|
||||||
default:
|
default:
|
||||||
|
if( StringTools.isEof(char) ) {
|
||||||
|
line = old;
|
||||||
|
error(EUnterminatedString, p1, p1);
|
||||||
|
}
|
||||||
invalidChar(char);
|
invalidChar(char);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// encode k in UTF8
|
b.addChar(k);
|
||||||
if( k <= 0x7F )
|
|
||||||
b.writeByte(k);
|
|
||||||
else if( k <= 0x7FF ) {
|
|
||||||
b.writeByte( 0xC0 | (k >> 6));
|
|
||||||
b.writeByte( 0x80 | (k & 63));
|
|
||||||
} else {
|
|
||||||
b.writeByte( 0xE0 | (k >> 12) );
|
|
||||||
b.writeByte( 0x80 | ((k >> 6) & 63) );
|
|
||||||
b.writeByte( 0x80 | (k & 63) );
|
|
||||||
}
|
|
||||||
default: invalidChar(c);
|
default: invalidChar(c);
|
||||||
}
|
}
|
||||||
} else if( c == 92 )
|
} else if( c == 92 )
|
||||||
@@ -1203,10 +1308,10 @@ class Parser {
|
|||||||
break;
|
break;
|
||||||
else {
|
else {
|
||||||
if( c == 10 ) line++;
|
if( c == 10 ) line++;
|
||||||
b.writeByte(c);
|
b.addChar(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b.getBytes().toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function token() {
|
function token() {
|
||||||
@@ -1238,8 +1343,13 @@ class Parser {
|
|||||||
this.char = -1;
|
this.char = -1;
|
||||||
}
|
}
|
||||||
while( true ) {
|
while( true ) {
|
||||||
|
if( StringTools.isEof(char) ) {
|
||||||
|
this.char = char;
|
||||||
|
return TEof;
|
||||||
|
}
|
||||||
switch( char ) {
|
switch( char ) {
|
||||||
case 0: return TEof;
|
case 0:
|
||||||
|
return TEof;
|
||||||
case 32,9,13: // space, tab, CR
|
case 32,9,13: // space, tab, CR
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
tokenMin++;
|
tokenMin++;
|
||||||
@@ -1411,6 +1521,7 @@ class Parser {
|
|||||||
var prev = -1;
|
var prev = -1;
|
||||||
while( true ) {
|
while( true ) {
|
||||||
char = readChar();
|
char = readChar();
|
||||||
|
if( StringTools.isEof(char) ) char = 0;
|
||||||
if( !ops[char] || prev == '='.code ) {
|
if( !ops[char] || prev == '='.code ) {
|
||||||
if( op.charCodeAt(0) == '/'.code )
|
if( op.charCodeAt(0) == '/'.code )
|
||||||
return tokenComment(op,char);
|
return tokenComment(op,char);
|
||||||
@@ -1425,6 +1536,7 @@ class Parser {
|
|||||||
var id = String.fromCharCode(char);
|
var id = String.fromCharCode(char);
|
||||||
while( true ) {
|
while( true ) {
|
||||||
char = readChar();
|
char = readChar();
|
||||||
|
if( StringTools.isEof(char) ) char = 0;
|
||||||
if( !idents[char] ) {
|
if( !idents[char] ) {
|
||||||
this.char = char;
|
this.char = char;
|
||||||
return TId(id);
|
return TId(id);
|
||||||
@@ -1530,14 +1642,11 @@ class Parser {
|
|||||||
var c = op.charCodeAt(1);
|
var c = op.charCodeAt(1);
|
||||||
var s = input;
|
var s = input;
|
||||||
if( c == '/'.code ) { // comment
|
if( c == '/'.code ) { // comment
|
||||||
try {
|
while( char != '\r'.code && char != '\n'.code ) {
|
||||||
while( char != '\r'.code && char != '\n'.code ) {
|
char = readChar();
|
||||||
incPos();
|
if( StringTools.isEof(char) ) break;
|
||||||
char = s.readByte();
|
|
||||||
}
|
|
||||||
this.char = char;
|
|
||||||
} catch( e : Dynamic ) {
|
|
||||||
}
|
}
|
||||||
|
this.char = char;
|
||||||
return token();
|
return token();
|
||||||
}
|
}
|
||||||
if( c == '*'.code ) { /* comment */
|
if( c == '*'.code ) { /* comment */
|
||||||
@@ -1546,21 +1655,24 @@ class Parser {
|
|||||||
this.char = char;
|
this.char = char;
|
||||||
return token();
|
return token();
|
||||||
}
|
}
|
||||||
try {
|
while( true ) {
|
||||||
while( true ) {
|
while( char != '*'.code ) {
|
||||||
while( char != '*'.code ) {
|
if( char == '\n'.code ) line++;
|
||||||
if( char == '\n'.code ) line++;
|
char = readChar();
|
||||||
incPos();
|
if( StringTools.isEof(char) ) {
|
||||||
char = s.readByte();
|
line = old;
|
||||||
}
|
error(EUnterminatedComment, tokenMin, tokenMin);
|
||||||
incPos();
|
|
||||||
char = s.readByte();
|
|
||||||
if( char == '/'.code )
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch( e : Dynamic ) {
|
char = readChar();
|
||||||
line = old;
|
if( StringTools.isEof(char) ) {
|
||||||
error(EUnterminatedComment, tokenMin, tokenMin);
|
line = old;
|
||||||
|
error(EUnterminatedComment, tokenMin, tokenMin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( char == '/'.code )
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return token();
|
return token();
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-1
@@ -48,6 +48,9 @@ class Printer {
|
|||||||
|
|
||||||
function type( t : CType ) {
|
function type( t : CType ) {
|
||||||
switch( t ) {
|
switch( t ) {
|
||||||
|
case CTOpt(t):
|
||||||
|
add('?');
|
||||||
|
type(t);
|
||||||
case CTPath(path, params):
|
case CTPath(path, params):
|
||||||
add(path.join("."));
|
add(path.join("."));
|
||||||
if( params != null ) {
|
if( params != null ) {
|
||||||
@@ -59,6 +62,19 @@ class Printer {
|
|||||||
}
|
}
|
||||||
add(">");
|
add(">");
|
||||||
}
|
}
|
||||||
|
case CTNamed(name, t):
|
||||||
|
add(name);
|
||||||
|
add(':');
|
||||||
|
type(t);
|
||||||
|
case CTFun(args, ret) if (Lambda.exists(args, function (a) return a.match(CTNamed(_, _)))):
|
||||||
|
add('(');
|
||||||
|
for (a in args)
|
||||||
|
switch a {
|
||||||
|
case CTNamed(_, _): type(a);
|
||||||
|
default: type(CTNamed('_', a));
|
||||||
|
}
|
||||||
|
add(')->');
|
||||||
|
type(ret);
|
||||||
case CTFun(args, ret):
|
case CTFun(args, ret):
|
||||||
if( args.length == 0 )
|
if( args.length == 0 )
|
||||||
add("Void -> ");
|
add("Void -> ");
|
||||||
@@ -300,6 +316,12 @@ class Printer {
|
|||||||
}
|
}
|
||||||
add(" ");
|
add(" ");
|
||||||
expr(e);
|
expr(e);
|
||||||
|
case ECheckType(e, t):
|
||||||
|
add("(");
|
||||||
|
expr(e);
|
||||||
|
add(" : ");
|
||||||
|
addType(t);
|
||||||
|
add(")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +331,7 @@ class Printer {
|
|||||||
|
|
||||||
public static function errorToString( e : Expr.Error ) {
|
public static function errorToString( e : Expr.Error ) {
|
||||||
var message = switch( #if hscriptPos e.e #else e #end ) {
|
var message = switch( #if hscriptPos e.e #else e #end ) {
|
||||||
case EInvalidChar(c): "Invalid character: '"+String.fromCharCode(c)+"' ("+c+")";
|
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF" : String.fromCharCode(c))+"' ("+c+")";
|
||||||
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
||||||
case EUnterminatedString: "Unterminated string";
|
case EUnterminatedString: "Unterminated string";
|
||||||
case EUnterminatedComment: "Unterminated comment";
|
case EUnterminatedComment: "Unterminated comment";
|
||||||
|
|||||||
+20
-8
@@ -25,7 +25,7 @@ import hscript.Expr;
|
|||||||
class Tools {
|
class Tools {
|
||||||
|
|
||||||
public static function iter( e : Expr, f : Expr -> Void ) {
|
public static function iter( e : Expr, f : Expr -> Void ) {
|
||||||
switch( #if hscriptPos e.e #else e #end ) {
|
switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_):
|
case EConst(_), EIdent(_):
|
||||||
case EVar(_, _, e): if( e != null ) f(e);
|
case EVar(_, _, e): if( e != null ) f(e);
|
||||||
case EParent(e): f(e);
|
case EParent(e): f(e);
|
||||||
@@ -56,16 +56,13 @@ class Tools {
|
|||||||
}
|
}
|
||||||
if( def != null ) f(def);
|
if( def != null ) f(def);
|
||||||
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
|
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
|
||||||
|
case ECheckType(e,_): f(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function map( e : Expr, f : Expr -> Expr ) {
|
public static function map( e : Expr, f : Expr -> Expr ) {
|
||||||
#if hscriptPos
|
var edef = switch( expr(e) ) {
|
||||||
var edef = switch( e.e ) {
|
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
||||||
#else
|
|
||||||
return switch( 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 EVar(n, t, e): EVar(n, t, if( e != null ) f(e) else null);
|
||||||
case EParent(e): EParent(f(e));
|
case EParent(e): EParent(f(e));
|
||||||
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
case EBlock(el): EBlock([for( e in el ) f(e)]);
|
||||||
@@ -88,9 +85,24 @@ class Tools {
|
|||||||
case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2));
|
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 ESwitch(e, cases, def): ESwitch(f(e), [for( c in cases ) { values : [for( v in c.values ) f(v)], expr : f(c.expr) } ], def == null ? null : f(def));
|
||||||
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
|
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
|
||||||
|
case ECheckType(e,t): ECheckType(f(e), t);
|
||||||
}
|
}
|
||||||
|
return mk(edef, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static inline function expr( e : Expr ) : ExprDef {
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return { e : edef, pmin : e.pmin, pmax : e.pmax, origin : e.origin, line : e.line };
|
return e.e;
|
||||||
|
#else
|
||||||
|
return e;
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
public static inline function mk( e : ExprDef, p : Expr ) {
|
||||||
|
#if hscriptPos
|
||||||
|
return { e : e, pmin : p.pmin, pmax : p.pmax, origin : p.origin, line : p.line };
|
||||||
|
#else
|
||||||
|
return e;
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
set PATH="C:\Program Files\7-Zip";%PATH%
|
||||||
rm -rf release
|
rm -rf release
|
||||||
mkdir release
|
mkdir release
|
||||||
cp haxelib.json README.md extraParams.hxml release
|
cp haxelib.json README.md extraParams.hxml release
|
||||||
|
|||||||
Reference in New Issue
Block a user