Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f2dec1634 | ||
|
|
51188173bb | ||
|
|
d0797ad5d8 | ||
|
|
9b37bd532e | ||
|
|
333352edcf | ||
|
|
05783773af | ||
|
|
59ee20ee7a | ||
|
|
87f2c1b062 | ||
|
|
b85cefea56 | ||
|
|
2e28f863f3 | ||
|
|
ddaa4d1741 | ||
|
|
732bd1520a | ||
|
|
1d67946f3f | ||
|
|
fab6d7e662 | ||
|
|
6e20578a81 | ||
|
|
dc5282c32e | ||
|
|
812abae6e5 | ||
|
|
b3b512d027 | ||
|
|
ed296c4c7f | ||
|
|
595bb47249 | ||
|
|
daad1a4fa8 | ||
|
|
daef1ac198 | ||
|
|
3b9d88b252 | ||
|
|
809f8229b4 | ||
|
|
ffb1ee2523 | ||
|
|
0903718314 | ||
|
|
e0cb883ae4 | ||
|
|
17449dd9d5 | ||
|
|
7963631a1d | ||
|
|
77d88f4b34 | ||
|
|
c5e3ab1162 | ||
|
|
75041c1db9 | ||
|
|
558a4c0782 | ||
|
|
995c3b9c8e | ||
|
|
0a64bca9ce | ||
|
|
b7b12b6cbb | ||
|
|
5684ca8671 | ||
|
|
3c81360dc2 | ||
|
|
fc50ebdf90 | ||
|
|
4d6e8db5ff | ||
|
|
938ffac57e | ||
|
|
50aaffb101 | ||
|
|
4f9b449c6e | ||
|
|
c1a36a3f4b | ||
|
|
4ca6e2a680 | ||
|
|
11db805c34 | ||
|
|
f1f700ab69 | ||
|
|
9eeb8ddb80 | ||
|
|
95de26a6d0 | ||
|
|
88c2e28dbc | ||
|
|
30b7a9e4d4 | ||
|
|
37542065d6 | ||
|
|
c9608f7760 | ||
|
|
6ba54b0e77 | ||
|
|
f9bb3105c8 | ||
|
|
4b5baa9b5f | ||
|
|
6dedd87260 | ||
|
|
91317222fb | ||
|
|
494953a8cc | ||
|
|
ae4d8be50c | ||
|
|
d34790e05c | ||
|
|
b77e15c6d6 | ||
|
|
54195d5811 | ||
|
|
9c7907f91a | ||
|
|
0601b8def6 | ||
|
|
841261f199 | ||
|
|
7124b6c4ce | ||
|
|
ad7beec559 | ||
|
|
bd4fc51392 | ||
|
|
54d994a879 | ||
|
|
891a085f2b | ||
|
|
e7ccd2e72d | ||
|
|
459a39e65d | ||
|
|
36eb0fca8b | ||
|
|
53b9e22f26 | ||
|
|
8ff3f5e351 | ||
|
|
e6a2c443cb | ||
|
|
4f25ab162d | ||
|
|
0520d9f187 | ||
|
|
cc3c21b7e3 | ||
|
|
ae9560124e | ||
|
|
085f4ec37e | ||
|
|
476c3a9cc9 | ||
|
|
1bc5ac8768 | ||
|
|
4bdff11b87 | ||
|
|
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 TestHScript 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,19 @@ 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 = () -> 55; f()", 55);
|
||||||
|
assertScript("var f = (x) -> x + 1; f(3)", 4);
|
||||||
|
assertScript("var f = (x:Int) -> x + 1; f(3)", 4);
|
||||||
|
assertScript("var f = (x,y) -> x + y; f(3,1)", 4);
|
||||||
|
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);
|
||||||
|
assertScript("var a = 10; var b = 5; a - -b", 15);
|
||||||
|
assertScript("var a = 10; var b = 5; a - b / 2", 7.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMap():Void {
|
function testMap():Void {
|
||||||
@@ -152,9 +166,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 TestHScript());
|
||||||
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
-1
@@ -1,3 +1,3 @@
|
|||||||
-main Test
|
-main TestHScript
|
||||||
-dce no
|
-dce no
|
||||||
-lib hx3compat
|
-lib hx3compat
|
||||||
@@ -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
|
|
||||||
+3
-3
@@ -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","HaxeFoundation"]
|
||||||
}
|
}
|
||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
bin/build-flash.hxml
|
bin/build-each.hxml
|
||||||
|
-hl bin/Test.hl
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<project version="2">
|
|
||||||
<!-- Output SWF options -->
|
|
||||||
<output>
|
|
||||||
<movie outputType="Application" />
|
|
||||||
<movie input="" />
|
|
||||||
<movie path="hscript.swf" />
|
|
||||||
<movie fps="30" />
|
|
||||||
<movie width="800" />
|
|
||||||
<movie height="600" />
|
|
||||||
<movie version="9" />
|
|
||||||
<movie minorVersion="0" />
|
|
||||||
<movie platform="Flash Player" />
|
|
||||||
<movie background="#FFFFFF" />
|
|
||||||
</output>
|
|
||||||
<!-- Other classes to be compiled into your SWF -->
|
|
||||||
<classpaths>
|
|
||||||
<!-- example: <class path="..." /> -->
|
|
||||||
</classpaths>
|
|
||||||
<!-- Build options -->
|
|
||||||
<build>
|
|
||||||
<option directives="" />
|
|
||||||
<option flashStrict="True" />
|
|
||||||
<option noInlineOnDebug="False" />
|
|
||||||
<option mainClass="Test" />
|
|
||||||
<option enabledebug="False" />
|
|
||||||
<option additional="-dce no" />
|
|
||||||
</build>
|
|
||||||
<!-- haxelib libraries -->
|
|
||||||
<haxelib>
|
|
||||||
<!-- example: <library name="..." /> -->
|
|
||||||
</haxelib>
|
|
||||||
<!-- Class files to compile (other referenced classes will automatically be included) -->
|
|
||||||
<compileTargets>
|
|
||||||
<!-- example: <compile path="..." /> -->
|
|
||||||
</compileTargets>
|
|
||||||
<!-- Assets to embed into the output SWF -->
|
|
||||||
<library>
|
|
||||||
<!-- example: <asset path="..." id="..." update="..." glyphs="..." mode="..." place="..." sharepoint="..." /> -->
|
|
||||||
</library>
|
|
||||||
<!-- Paths to exclude from the Project Explorer tree -->
|
|
||||||
<hiddenPaths>
|
|
||||||
<hidden path="haxelib.xml" />
|
|
||||||
<hidden path="hscript.hxml" />
|
|
||||||
<hidden path="hscript.js" />
|
|
||||||
<hidden path="hscript.n" />
|
|
||||||
<hidden path="hscript.swf" />
|
|
||||||
<hidden path="hscript9.swf" />
|
|
||||||
<hidden path="release.bat" />
|
|
||||||
<hidden path="release.zip" />
|
|
||||||
<hidden path="obj" />
|
|
||||||
</hiddenPaths>
|
|
||||||
<!-- Executed before build -->
|
|
||||||
<preBuildCommand />
|
|
||||||
<!-- Executed after build -->
|
|
||||||
<postBuildCommand alwaysRun="False" />
|
|
||||||
<!-- Other project options -->
|
|
||||||
<options>
|
|
||||||
<option showHiddenPaths="False" />
|
|
||||||
<option testMovie="Default" />
|
|
||||||
<option testMovieCommand="" />
|
|
||||||
</options>
|
|
||||||
<!-- Plugin storage -->
|
|
||||||
<storage />
|
|
||||||
</project>
|
|
||||||
+78
-36
@@ -22,13 +22,21 @@
|
|||||||
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;
|
||||||
var uid = 0;
|
var uid = 0;
|
||||||
|
public var asyncIdents : Map<String,Bool>;
|
||||||
|
|
||||||
static var nullExpr : Expr = #if hscriptPos { e : null, pmin : 0, pmax : 0, origin : "<null>", line : 0 } #else null #end;
|
static var nullExpr : Expr = #if hscriptPos { e : null, pmin : 0, pmax : 0, origin : "<null>", line : 0 } #else null #end;
|
||||||
static var nullId = mk(EIdent("null"), nullExpr);
|
static var nullId = mk(EIdent("null"), nullExpr);
|
||||||
@@ -68,35 +76,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,_):
|
||||||
|
if( name != null )
|
||||||
return toCps(e, null, 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 +132,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 +160,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 +178,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 ) {
|
||||||
@@ -175,11 +208,19 @@ class Async {
|
|||||||
return syncFlag;
|
return syncFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline function isAsyncIdent( id : String ) {
|
||||||
|
return asyncIdents == null || asyncIdents.exists(id);
|
||||||
|
}
|
||||||
|
|
||||||
function checkSync( e : Expr ) {
|
function checkSync( e : Expr ) {
|
||||||
if( !syncFlag )
|
if( !syncFlag )
|
||||||
return;
|
return;
|
||||||
switch( expr(e) ) {
|
switch( expr(e) ) {
|
||||||
case ECall(_), EFunction(_):
|
case ECall(expr(_) => EIdent(i),_) if( isAsyncIdent(i) || vars.get(i) == Defined ):
|
||||||
|
syncFlag = false;
|
||||||
|
case ECall(expr(_) => EField(_,i),_) if( isAsyncIdent(i) ):
|
||||||
|
syncFlag = false;
|
||||||
|
case EFunction(_,_,name,_) if( name != null ):
|
||||||
syncFlag = false;
|
syncFlag = false;
|
||||||
case EMeta("sync" | "async", _, _):
|
case EMeta("sync" | "async", _, _):
|
||||||
// isolated from the sync part
|
// isolated from the sync part
|
||||||
@@ -189,11 +230,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 +247,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 +257,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 +280,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 +290,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 +298,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 +346,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 +393,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 +415,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);
|
||||||
|
|||||||
+14
-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;
|
||||||
}
|
}
|
||||||
@@ -143,6 +140,10 @@ class Bytes {
|
|||||||
#end
|
#end
|
||||||
bout.addByte(Type.enumIndex(e));
|
bout.addByte(Type.enumIndex(e));
|
||||||
switch( e ) {
|
switch( e ) {
|
||||||
|
case EImport(c):
|
||||||
|
// TODO
|
||||||
|
case EClass(_, _, _, _):
|
||||||
|
// TODO
|
||||||
case EConst(c):
|
case EConst(c):
|
||||||
doEncodeConst(c);
|
doEncodeConst(c);
|
||||||
case EIdent(v):
|
case EIdent(v):
|
||||||
@@ -249,11 +250,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 +380,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:
|
||||||
|
|||||||
+1241
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,105 @@
|
|||||||
|
package hscript;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class CustomClassHandler implements IHScriptCustomConstructor {
|
||||||
|
public static var staticHandler = new StaticHandler();
|
||||||
|
|
||||||
|
public var ogInterp:Interp;
|
||||||
|
public var name:String;
|
||||||
|
public var fields:Array<Expr>;
|
||||||
|
public var extend:String;
|
||||||
|
public var interfaces:Array<String>;
|
||||||
|
|
||||||
|
public function new(ogInterp:Interp, name:String, fields:Array<Expr>, ?extend:String, ?interfaces:Array<String>) {
|
||||||
|
this.ogInterp = ogInterp;
|
||||||
|
this.name = name;
|
||||||
|
this.fields = fields;
|
||||||
|
this.extend = extend;
|
||||||
|
this.interfaces = interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hnew(args:Array<Dynamic>):Dynamic {
|
||||||
|
var interp = new Interp();
|
||||||
|
|
||||||
|
interp.errorHandler = ogInterp.errorHandler;
|
||||||
|
|
||||||
|
var cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
|
||||||
|
var _class = Type.createInstance(cl, args);
|
||||||
|
|
||||||
|
var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
|
||||||
|
var capturedLocals:Map<String, {r:Dynamic, depth:Int}> = [];
|
||||||
|
for(k=>e in __capturedLocals)
|
||||||
|
if (e != null && e.depth <= 0)
|
||||||
|
capturedLocals.set(k, e);
|
||||||
|
|
||||||
|
var disallowCopy = Type.getInstanceFields(cl);
|
||||||
|
|
||||||
|
//trace("Locals");
|
||||||
|
for (key => value in capturedLocals) {
|
||||||
|
if(!disallowCopy.contains(key)) {
|
||||||
|
interp.locals.set(key, {r: value, depth: -1});
|
||||||
|
//trace(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//trace("Variables");
|
||||||
|
for (key => value in ogInterp.variables) {
|
||||||
|
if(!disallowCopy.contains(key)) {
|
||||||
|
interp.variables.set(key, value);
|
||||||
|
//trace(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(expr in fields) {
|
||||||
|
@:privateAccess
|
||||||
|
interp.exprReturn(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
interp.variables.set("super", staticHandler);
|
||||||
|
|
||||||
|
_class.__interp = interp;
|
||||||
|
interp.scriptObject = _class;
|
||||||
|
|
||||||
|
var newFunc = interp.variables.get("new");
|
||||||
|
if(newFunc != null) {
|
||||||
|
Reflect.callMethod(null, newFunc, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(variable => value in interp.variables) {
|
||||||
|
if(variable == "this") continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toString():String {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemplateClass implements IHScriptCustomBehaviour {
|
||||||
|
public var __interp:Interp;
|
||||||
|
|
||||||
|
public function hset(name:String, val:Dynamic):Dynamic {
|
||||||
|
if(this.__interp.variables.exists("set_" + name)) {
|
||||||
|
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
|
||||||
|
}
|
||||||
|
if (this.__interp.variables.exists(name)) {
|
||||||
|
this.__interp.variables.set(name, val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
Reflect.setProperty(this, name, val);
|
||||||
|
return Reflect.field(this, name);
|
||||||
|
}
|
||||||
|
public function hget(name:String):Dynamic {
|
||||||
|
if(this.__interp.variables.exists("get_" + name))
|
||||||
|
return this.__interp.variables.get("get_" + name)();
|
||||||
|
if (this.__interp.variables.exists(name))
|
||||||
|
return this.__interp.variables.get(name);
|
||||||
|
return Reflect.getProperty(this, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StaticHandler {
|
||||||
|
public function new() {}
|
||||||
|
}
|
||||||
+13
-4
@@ -40,14 +40,15 @@ typedef Expr = {
|
|||||||
}
|
}
|
||||||
enum ExprDef {
|
enum ExprDef {
|
||||||
#else
|
#else
|
||||||
|
typedef ExprDef = Expr;
|
||||||
enum Expr {
|
enum Expr {
|
||||||
#end
|
#end
|
||||||
EConst( c : Const );
|
EConst( c : Const );
|
||||||
EIdent( v : String );
|
EIdent( v : String );
|
||||||
EVar( n : String, ?t : CType, ?e : Expr );
|
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
|
||||||
EParent( e : Expr );
|
EParent( e : Expr );
|
||||||
EBlock( e : Array<Expr> );
|
EBlock( e : Array<Expr> );
|
||||||
EField( e : Expr, f : String );
|
EField( e : Expr, f : String , ?safe : Bool );
|
||||||
EBinop( op : String, e1 : Expr, e2 : Expr );
|
EBinop( op : String, e1 : Expr, e2 : Expr );
|
||||||
EUnop( op : String, prefix : Bool, e : Expr );
|
EUnop( op : String, prefix : Bool, e : Expr );
|
||||||
ECall( e : Expr, params : Array<Expr> );
|
ECall( e : Expr, params : Array<Expr> );
|
||||||
@@ -56,10 +57,10 @@ enum Expr {
|
|||||||
EFor( v : String, it : Expr, e : Expr );
|
EFor( v : String, it : Expr, e : Expr );
|
||||||
EBreak;
|
EBreak;
|
||||||
EContinue;
|
EContinue;
|
||||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType );
|
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||||
EReturn( ?e : Expr );
|
EReturn( ?e : Expr );
|
||||||
EArray( e : Expr, index : Expr );
|
EArray( e : Expr, index : Expr );
|
||||||
EArrayDecl( e : Array<Expr> );
|
EArrayDecl( e : Array<Expr>, ?wantedType: CType );
|
||||||
ENew( cl : String, params : Array<Expr> );
|
ENew( cl : String, params : Array<Expr> );
|
||||||
EThrow( e : Expr );
|
EThrow( e : Expr );
|
||||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||||
@@ -68,6 +69,10 @@ 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 );
|
||||||
|
|
||||||
|
EImport( c : String, ?asname:String );
|
||||||
|
EClass( name:String, fields:Array<Expr>, ?extend:String, interfaces:Array<String> );
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||||
@@ -79,6 +84,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
|
||||||
@@ -113,6 +120,8 @@ enum Error {
|
|||||||
EInvalidOp( op : String );
|
EInvalidOp( op : String );
|
||||||
EInvalidAccess( f : String );
|
EInvalidAccess( f : String );
|
||||||
ECustom( msg : String );
|
ECustom( msg : String );
|
||||||
|
EInvalidClass( className : String);
|
||||||
|
EAlreadyExistingClass( className : String);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package hscript;
|
||||||
|
|
||||||
|
interface IHScriptCustomBehaviour {
|
||||||
|
public function hset(name:String, val:Dynamic):Dynamic;
|
||||||
|
public function hget(name:String):Dynamic;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package hscript;
|
||||||
|
|
||||||
|
interface IHScriptCustomConstructor {
|
||||||
|
public function hnew(args:Array<Dynamic>):Dynamic;
|
||||||
|
}
|
||||||
+439
-107
@@ -19,9 +19,23 @@
|
|||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* YoshiCrafter Engine fixes:
|
||||||
|
* - Added Error handler
|
||||||
|
* - Added Imports
|
||||||
|
* - Added @:bypassAccessor
|
||||||
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
|
|
||||||
|
import haxe.iterators.StringKeyValueIteratorUnicode;
|
||||||
|
import haxe.EnumTools;
|
||||||
|
import haxe.display.Protocol.InitializeResult;
|
||||||
import haxe.PosInfos;
|
import haxe.PosInfos;
|
||||||
import hscript.Expr;
|
import hscript.Expr;
|
||||||
|
import haxe.Constraints.IMap;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
private enum Stop {
|
private enum Stop {
|
||||||
SBreak;
|
SBreak;
|
||||||
@@ -30,45 +44,86 @@ private enum Stop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Interp {
|
class Interp {
|
||||||
|
public var scriptObject(default, set):Dynamic;
|
||||||
|
public function set_scriptObject(v:Dynamic) {
|
||||||
|
__instanceFields = (v == null) ? [] : Type.getInstanceFields(Type.getClass(v));
|
||||||
|
return scriptObject = v;
|
||||||
|
}
|
||||||
|
public var errorHandler:Error->Void;
|
||||||
|
public var importFailedCallback:Array<String>->Bool;
|
||||||
#if haxe3
|
#if haxe3
|
||||||
|
public var customClasses:Map<String, Dynamic>;
|
||||||
public var variables:Map<String, Dynamic>;
|
public var variables:Map<String, Dynamic>;
|
||||||
var locals : Map<String,{ r : Dynamic }>;
|
public var publicVariables:Map<String, Dynamic>;
|
||||||
|
public var staticVariables:Map<String, Dynamic>;
|
||||||
|
|
||||||
|
public var locals:Map<String, {r:Dynamic, depth:Int}>;
|
||||||
var binops:Map<String, Expr->Expr->Dynamic>;
|
var binops:Map<String, Expr->Expr->Dynamic>;
|
||||||
#else
|
#else
|
||||||
|
public var customClasses:Hash<Dynamic>;
|
||||||
public var variables:Hash<Dynamic>;
|
public var variables:Hash<Dynamic>;
|
||||||
var locals : Hash<{ r : Dynamic }>;
|
public var publicVariables:Hash<Dynamic>;
|
||||||
|
public var staticVariables:Hash<Dynamic>;
|
||||||
|
|
||||||
|
public var locals:Hash<{r:Dynamic, depth:Int}>;
|
||||||
var binops:Hash<Expr->Expr->Dynamic>;
|
var binops:Hash<Expr->Expr->Dynamic>;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
var depth : Int;
|
var depth:Int = 0;
|
||||||
var inTry:Bool;
|
var inTry:Bool;
|
||||||
var declared : Array<{ n : String, old : { r : Dynamic } }>;
|
var declared:Array<{n:String, old:{r:Dynamic, depth:Int}, depth:Int}>;
|
||||||
var returnValue:Dynamic;
|
var returnValue:Dynamic;
|
||||||
|
|
||||||
|
var isBypassAccessor:Bool = false;
|
||||||
|
|
||||||
|
public var importEnabled:Bool = true;
|
||||||
|
|
||||||
|
public var allowStaticVariables:Bool = false;
|
||||||
|
public var allowPublicVariables:Bool = false;
|
||||||
|
|
||||||
|
public var importBlocklist:Array<String> = [
|
||||||
|
// "flixel.FlxG"
|
||||||
|
];
|
||||||
|
|
||||||
|
var __instanceFields:Array<String> = [];
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
var curExpr:Expr;
|
var curExpr:Expr;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
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
|
||||||
|
customClasses = new Map<String, Dynamic>();
|
||||||
|
variables = new Map<String, Dynamic>();
|
||||||
|
publicVariables = new Map<String, Dynamic>();
|
||||||
|
staticVariables = new Map<String, Dynamic>();
|
||||||
|
#else
|
||||||
|
customClasses = new Hash();
|
||||||
|
variables = new Hash();
|
||||||
|
publicVariables = new Hash();
|
||||||
|
staticVariables = 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);
|
||||||
variables.set("trace", Reflect.makeVarArgs(function(el) {
|
variables.set("trace", Reflect.makeVarArgs(function(el) {
|
||||||
var inf = posInfos();
|
var inf = posInfos();
|
||||||
var v = el.shift();
|
var v = el.shift();
|
||||||
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 {
|
||||||
@@ -106,7 +161,16 @@ class Interp {
|
|||||||
binops.set("||", function(e1, e2) return me.expr(e1) == true || me.expr(e2) == true);
|
binops.set("||", function(e1, e2) return me.expr(e1) == true || me.expr(e2) == true);
|
||||||
binops.set("&&", function(e1, e2) return me.expr(e1) == true && me.expr(e2) == true);
|
binops.set("&&", function(e1, e2) return me.expr(e1) == true && me.expr(e2) == true);
|
||||||
binops.set("=", assign);
|
binops.set("=", assign);
|
||||||
binops.set("...",function(e1,e2) return new #if (haxe_211 || haxe3) IntIterator #else IntIter #end(me.expr(e1),me.expr(e2)));
|
binops.set("??", function(e1, e2) {
|
||||||
|
var expr1:Dynamic = me.expr(e1);
|
||||||
|
return expr1 == null ? me.expr(e2) : expr1;
|
||||||
|
});
|
||||||
|
binops.set("...", function(e1, e2) return new
|
||||||
|
#if (haxe_211 || haxe3)
|
||||||
|
IntIterator
|
||||||
|
#else
|
||||||
|
IntIter
|
||||||
|
#end(me.expr(e1), me.expr(e2)));
|
||||||
assignOp("+=", function(v1:Dynamic, v2:Dynamic) return v1 + v2);
|
assignOp("+=", function(v1:Dynamic, v2:Dynamic) return v1 + v2);
|
||||||
assignOp("-=", function(v1:Float, v2:Float) return v1 - v2);
|
assignOp("-=", function(v1:Float, v2:Float) return v1 - v2);
|
||||||
assignOp("*=", function(v1:Float, v2:Float) return v1 * v2);
|
assignOp("*=", function(v1:Float, v2:Float) return v1 * v2);
|
||||||
@@ -118,17 +182,53 @@ class Interp {
|
|||||||
assignOp("<<=", function(v1, v2) return v1 << v2);
|
assignOp("<<=", function(v1, v2) return v1 << v2);
|
||||||
assignOp(">>=", function(v1, v2) return v1 >> v2);
|
assignOp(">>=", function(v1, v2) return v1 >> v2);
|
||||||
assignOp(">>>=", function(v1, v2) return v1 >>> v2);
|
assignOp(">>>=", function(v1, v2) return v1 >>> v2);
|
||||||
|
assignOp("is", function(v1, v2) return Std.isOfType(v1, v2));
|
||||||
|
assignOp("??=", function(v1, v2) return v1 == null ? v2 : v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setVar(name:String, v:Dynamic) {
|
||||||
|
if (allowStaticVariables && staticVariables.exists(name))
|
||||||
|
staticVariables.set(name, v);
|
||||||
|
else if (allowPublicVariables && publicVariables.exists(name))
|
||||||
|
publicVariables.set(name, v);
|
||||||
|
else
|
||||||
|
variables.set(name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
variables.set(id,v)
|
if (!variables.exists(id) && !staticVariables.exists(id) && !publicVariables.exists(id) && scriptObject != null) {
|
||||||
else
|
if (Type.typeof(scriptObject) == TObject) {
|
||||||
|
Reflect.setField(scriptObject, id, v);
|
||||||
|
} else {
|
||||||
|
if (isBypassAccessor) {
|
||||||
|
if (__instanceFields.contains(id)) {
|
||||||
|
Reflect.setField(scriptObject, id, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (__instanceFields.contains(id)) {
|
||||||
|
Reflect.setProperty(scriptObject, id, v);
|
||||||
|
} else if (__instanceFields.contains('set_$id')) { // setter
|
||||||
|
Reflect.getProperty(scriptObject, 'set_$id')(v);
|
||||||
|
} else {
|
||||||
|
setVar(id, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setVar(id, v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
l.r = v;
|
l.r = v;
|
||||||
|
if (l.depth == 0) {
|
||||||
|
setVar(id, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
case EField(e, f):
|
case EField(e, f):
|
||||||
v = set(expr(e), f, v);
|
v = set(expr(e), f, v);
|
||||||
case EArray(e, index):
|
case EArray(e, index):
|
||||||
@@ -136,8 +236,7 @@ class Interp {
|
|||||||
var index:Dynamic = expr(index);
|
var index:Dynamic = expr(index);
|
||||||
if (isMap(arr)) {
|
if (isMap(arr)) {
|
||||||
setMapValue(arr, index, v);
|
setMapValue(arr, index, v);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
arr[index] = v;
|
arr[index] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,12 +253,19 @@ 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));
|
||||||
if( l == null )
|
if (l == null) {
|
||||||
variables.set(id,v)
|
if (__instanceFields.contains(id)) {
|
||||||
|
Reflect.setProperty(scriptObject, id, v);
|
||||||
|
} else if (__instanceFields.contains('set_$id')) { // setter
|
||||||
|
Reflect.getProperty(scriptObject, 'set_$id')(v);
|
||||||
|
} else {
|
||||||
|
setVar(id, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
l.r = v;
|
l.r = v;
|
||||||
case EField(e, f):
|
case EField(e, f):
|
||||||
@@ -172,8 +278,7 @@ class Interp {
|
|||||||
if (isMap(arr)) {
|
if (isMap(arr)) {
|
||||||
v = fop(getMapValue(arr, index), expr(e2));
|
v = fop(getMapValue(arr, index), expr(e2));
|
||||||
setMapValue(arr, index, v);
|
setMapValue(arr, index, v);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
v = fop(arr[index], expr(e2));
|
v = fop(arr[index], expr(e2));
|
||||||
arr[index] = v;
|
arr[index] = v;
|
||||||
}
|
}
|
||||||
@@ -191,12 +296,17 @@ class Interp {
|
|||||||
switch (e) {
|
switch (e) {
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
var l = locals.get(id);
|
var l = locals.get(id);
|
||||||
var v : Dynamic = (l == null) ? variables.get(id) : l.r;
|
var v:Dynamic = (l == null) ? resolve(id) : l.r;
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
v += delta;
|
v += delta;
|
||||||
if( l == null ) variables.set(id,v) else l.r = v;
|
if (l == null)
|
||||||
} else
|
setVar(id, v)
|
||||||
if( l == null ) variables.set(id,v + delta) else l.r = v + delta;
|
else
|
||||||
|
l.r = v;
|
||||||
|
} else if (l == null)
|
||||||
|
setVar(id, v + delta)
|
||||||
|
else
|
||||||
|
l.r = v + delta;
|
||||||
return v;
|
return v;
|
||||||
case EField(e, f):
|
case EField(e, f):
|
||||||
var obj = expr(e);
|
var obj = expr(e);
|
||||||
@@ -215,13 +325,11 @@ class Interp {
|
|||||||
if (prefix) {
|
if (prefix) {
|
||||||
v += delta;
|
v += delta;
|
||||||
setMapValue(arr, index, v);
|
setMapValue(arr, index, v);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
setMapValue(arr, index, v + delta);
|
setMapValue(arr, index, v + delta);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var v = arr[index];
|
var v = arr[index];
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
v += delta;
|
v += delta;
|
||||||
@@ -247,22 +355,37 @@ class Interp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function exprReturn(e):Dynamic {
|
function exprReturn(e):Dynamic {
|
||||||
|
try {
|
||||||
try {
|
try {
|
||||||
return expr(e);
|
return expr(e);
|
||||||
} catch (e:Stop) {
|
} catch (e:Stop) {
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case SBreak: throw "Invalid break";
|
case SBreak:
|
||||||
case SContinue: throw "Invalid continue";
|
throw "Invalid break";
|
||||||
|
case SContinue:
|
||||||
|
throw "Invalid continue";
|
||||||
case SReturn:
|
case SReturn:
|
||||||
var v = returnValue;
|
var v = returnValue;
|
||||||
returnValue = null;
|
returnValue = null;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
error(ECustom('${e.toString()}'));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch(e:Error) {
|
||||||
|
if (errorHandler != null)
|
||||||
|
errorHandler(e);
|
||||||
|
else
|
||||||
|
throw e;
|
||||||
|
return null;
|
||||||
|
} catch(e) {
|
||||||
|
trace(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function duplicate<T>( h : #if haxe3 Map < String, T > #else Hash<T> #end ) {
|
public function duplicate<T>(h:#if haxe3 Map<String, T> #else Hash<T> #end) {
|
||||||
#if haxe3
|
#if haxe3
|
||||||
var h2 = new Map();
|
var h2 = new Map();
|
||||||
#else
|
#else
|
||||||
@@ -280,17 +403,14 @@ 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;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,12 +422,32 @@ class Interp {
|
|||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolve( id : String ) : Dynamic {
|
public function resolve(id:String, doException:Bool = true):Dynamic {
|
||||||
|
id = StringTools.trim(id);
|
||||||
var l = locals.get(id);
|
var l = locals.get(id);
|
||||||
if (l != null)
|
if (l != null)
|
||||||
return l.r;
|
return l.r;
|
||||||
|
|
||||||
var v = variables.get(id);
|
var v = variables.get(id);
|
||||||
if( v == null && !variables.exists(id) )
|
for(map in [variables, publicVariables, staticVariables, customClasses])
|
||||||
|
if (map.exists(id))
|
||||||
|
return map[id];
|
||||||
|
|
||||||
|
if (scriptObject != null) {
|
||||||
|
// search in object
|
||||||
|
if (id == "this") {
|
||||||
|
return scriptObject;
|
||||||
|
} else if ((Type.typeof(scriptObject) == TObject) && Reflect.hasField(scriptObject, id)) {
|
||||||
|
return Reflect.field(scriptObject, id);
|
||||||
|
} else {
|
||||||
|
if (__instanceFields.contains(id)) {
|
||||||
|
return Reflect.getProperty(scriptObject, id);
|
||||||
|
} else if (__instanceFields.contains('get_$id')) { // getter
|
||||||
|
return Reflect.getProperty(scriptObject, 'get_$id')();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (doException)
|
||||||
error(EUnknownVariable(id));
|
error(EUnknownVariable(id));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -318,6 +458,78 @@ class Interp {
|
|||||||
var e = e.e;
|
var e = e.e;
|
||||||
#end
|
#end
|
||||||
switch (e) {
|
switch (e) {
|
||||||
|
case EClass(name, fields, extend, interfaces):
|
||||||
|
if (customClasses.exists(name))
|
||||||
|
error(EAlreadyExistingClass(name));
|
||||||
|
customClasses.set(name, new CustomClassHandler(this, name, fields, extend, interfaces));
|
||||||
|
case EImport(c, n):
|
||||||
|
if (!importEnabled)
|
||||||
|
return null;
|
||||||
|
var splitClassName = [for (e in c.split(".")) e.trim()];
|
||||||
|
var realClassName = splitClassName.join(".");
|
||||||
|
var claVarName = splitClassName[splitClassName.length - 1];
|
||||||
|
var toSetName = n != null ? n : claVarName;
|
||||||
|
var oldClassName = realClassName;
|
||||||
|
var oldSplitName = splitClassName.copy();
|
||||||
|
|
||||||
|
if (variables.exists(toSetName)) // class is already imported
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (importBlocklist.contains(realClassName))
|
||||||
|
return null;
|
||||||
|
var cl = Type.resolveClass(realClassName);
|
||||||
|
if (cl == null)
|
||||||
|
cl = Type.resolveClass('${realClassName}_HSC');
|
||||||
|
|
||||||
|
var en = Type.resolveEnum(realClassName);
|
||||||
|
|
||||||
|
//trace(realClassName, cl, en, splitClassName);
|
||||||
|
|
||||||
|
// Allow for flixel.ui.FlxBar.FlxBarFillDirection;
|
||||||
|
if (cl == null && en == null) {
|
||||||
|
if(splitClassName.length > 1) {
|
||||||
|
splitClassName.splice(-2, 1); // Remove the last last item
|
||||||
|
realClassName = splitClassName.join(".");
|
||||||
|
|
||||||
|
if (importBlocklist.contains(realClassName))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
cl = Type.resolveClass(realClassName);
|
||||||
|
if (cl == null)
|
||||||
|
cl = Type.resolveClass('${realClassName}_HSC');
|
||||||
|
|
||||||
|
en = Type.resolveEnum(realClassName);
|
||||||
|
|
||||||
|
//trace(realClassName, cl, en, splitClassName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cl == null && en == null) {
|
||||||
|
if (importFailedCallback == null || !importFailedCallback(oldSplitName))
|
||||||
|
error(EInvalidClass(oldClassName));
|
||||||
|
} else {
|
||||||
|
if (en != null) {
|
||||||
|
// ENUM!!!!
|
||||||
|
var enumThingy = {};
|
||||||
|
for (c in en.getConstructors()) {
|
||||||
|
try {
|
||||||
|
Reflect.setField(enumThingy, c, en.createByName(c));
|
||||||
|
} catch(e) {
|
||||||
|
try {
|
||||||
|
Reflect.setField(enumThingy, c, Reflect.field(en, c));
|
||||||
|
} catch(ex) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
variables.set(toSetName, enumThingy);
|
||||||
|
} else {
|
||||||
|
variables.set(toSetName, cl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
case EConst(c):
|
case EConst(c):
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case CInt(v): return v;
|
case CInt(v): return v;
|
||||||
@@ -329,9 +541,18 @@ class Interp {
|
|||||||
}
|
}
|
||||||
case EIdent(id):
|
case EIdent(id):
|
||||||
return resolve(id);
|
return resolve(id);
|
||||||
case EVar(n,_,e):
|
case EVar(n, _, e, isPublic, isStatic):
|
||||||
declared.push({ n : n, old : locals.get(n) });
|
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||||
locals.set(n,{ r : (e == null)?null:expr(e) });
|
locals.set(n, {r: (e == null) ? null : expr(e), depth: depth});
|
||||||
|
if (depth == 0) {
|
||||||
|
if(isStatic == true) {
|
||||||
|
if(!staticVariables.exists(n)) {
|
||||||
|
staticVariables.set(n, locals[n].r);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
(isPublic ? publicVariables : variables).set(n, locals[n].r);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
case EParent(e):
|
case EParent(e):
|
||||||
return expr(e);
|
return expr(e);
|
||||||
@@ -342,11 +563,15 @@ class Interp {
|
|||||||
v = expr(e);
|
v = expr(e);
|
||||||
restore(old);
|
restore(old);
|
||||||
return v;
|
return v;
|
||||||
case EField(e,f):
|
case EField(e, f, s):
|
||||||
return get(expr(e),f);
|
var field = expr(e);
|
||||||
|
if(s && field == null)
|
||||||
|
return null;
|
||||||
|
return get(field, f);
|
||||||
case EBinop(op, e1, e2):
|
case EBinop(op, e1, e2):
|
||||||
var fop = binops.get(op);
|
var fop = binops.get(op);
|
||||||
if( fop == null ) error(EInvalidOp(op));
|
if (fop == null)
|
||||||
|
error(EInvalidOp(op));
|
||||||
return fop(e1, e2);
|
return fop(e1, e2);
|
||||||
case EUnop(op, prefix, e):
|
case EUnop(op, prefix, e):
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -372,10 +597,13 @@ 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, s):
|
||||||
var obj = expr(e);
|
var obj = expr(e);
|
||||||
if( obj == null ) error(EInvalidAccess(f));
|
if (obj == null) {
|
||||||
|
if(s) return null;
|
||||||
|
error(EInvalidAccess(f));
|
||||||
|
}
|
||||||
return fcall(obj, f, args);
|
return fcall(obj, f, args);
|
||||||
default:
|
default:
|
||||||
return call(null, expr(e), args);
|
return call(null, expr(e), args);
|
||||||
@@ -398,8 +626,13 @@ class Interp {
|
|||||||
case EReturn(e):
|
case EReturn(e):
|
||||||
returnValue = e == null ? null : expr(e);
|
returnValue = e == null ? null : expr(e);
|
||||||
throw SReturn;
|
throw SReturn;
|
||||||
case EFunction(params,fexpr,name,_):
|
case EFunction(params, fexpr, name, _, isPublic, isStatic, isOverride):
|
||||||
var capturedLocals = duplicate(locals);
|
var __capturedLocals = duplicate(locals);
|
||||||
|
var capturedLocals:Map<String, {r:Dynamic, depth:Int}> = [];
|
||||||
|
for(k=>e in __capturedLocals)
|
||||||
|
if (e != null && e.depth > 0)
|
||||||
|
capturedLocals.set(k, e);
|
||||||
|
|
||||||
var me = this;
|
var me = this;
|
||||||
var hasOpt = false, minParams = 0;
|
var hasOpt = false, minParams = 0;
|
||||||
for (p in params)
|
for (p in params)
|
||||||
@@ -408,11 +641,14 @@ class Interp {
|
|||||||
else
|
else
|
||||||
minParams++;
|
minParams++;
|
||||||
var f = function(args:Array<Dynamic>) {
|
var f = function(args:Array<Dynamic>) {
|
||||||
if( args.length != params.length ) {
|
if (me.locals == null || me.variables == null) return null;
|
||||||
|
|
||||||
|
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)
|
||||||
throw str;
|
str += " for function '" + name + "'";
|
||||||
|
error(ECustom(str));
|
||||||
}
|
}
|
||||||
// make sure mandatory args are forced
|
// make sure mandatory args are forced
|
||||||
var args2 = [];
|
var args2 = [];
|
||||||
@@ -433,8 +669,9 @@ class Interp {
|
|||||||
me.depth++;
|
me.depth++;
|
||||||
me.locals = me.duplicate(capturedLocals);
|
me.locals = me.duplicate(capturedLocals);
|
||||||
for (i in 0...params.length)
|
for (i in 0...params.length)
|
||||||
me.locals.set(params[i].name,{ r : args[i] });
|
me.locals.set(params[i].name, {r: args[i], depth: depth});
|
||||||
var r = null;
|
var r = null;
|
||||||
|
var oldDecl = declared.length;
|
||||||
if (inTry)
|
if (inTry)
|
||||||
try {
|
try {
|
||||||
r = me.exprReturn(fexpr);
|
r = me.exprReturn(fexpr);
|
||||||
@@ -449,6 +686,7 @@ class Interp {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
r = me.exprReturn(fexpr);
|
r = me.exprReturn(fexpr);
|
||||||
|
restore(oldDecl);
|
||||||
me.locals = old;
|
me.locals = old;
|
||||||
me.depth = depth;
|
me.depth = depth;
|
||||||
return r;
|
return r;
|
||||||
@@ -457,18 +695,26 @@ class Interp {
|
|||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
// global function
|
// global function
|
||||||
variables.set(name, f);
|
((isStatic && allowStaticVariables) ? staticVariables : ((isPublic && allowPublicVariables) ? publicVariables : variables)).set(name, f);
|
||||||
} else {
|
} else {
|
||||||
// function-in-function is a local function
|
// function-in-function is a local function
|
||||||
declared.push( { n : name, old : locals.get(name) } );
|
declared.push({n: name, old: locals.get(name), depth: depth});
|
||||||
var ref = { r : f };
|
var ref = {r: f, depth: depth};
|
||||||
locals.set(name, ref);
|
locals.set(name, ref);
|
||||||
capturedLocals.set(name, ref); // allow self-recursion
|
capturedLocals.set(name, ref); // allow self-recursion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
case EArrayDecl(arr):
|
case EArrayDecl(arr, wantedType):
|
||||||
if (arr.length > 0 && edef(arr[0]).match(EBinop("=>", _))) {
|
var isMap = false;
|
||||||
|
var isTypeMap = false;
|
||||||
|
if(!isMap && wantedType != null) {
|
||||||
|
isMap = wantedType.match(CTPath(["Map"], [_, _]));
|
||||||
|
isTypeMap = true;
|
||||||
|
} else {
|
||||||
|
isMap = arr.length > 0 && Tools.expr(arr[0]).match(EBinop("=>", _));
|
||||||
|
}
|
||||||
|
if (isMap) {
|
||||||
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,12 +722,12 @@ 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);
|
||||||
isAllString = isAllString && Std.is(key, String);
|
isAllString = isAllString && (key is String);
|
||||||
isAllInt = isAllInt && Std.is(key, Int);
|
isAllInt = isAllInt && (key is Int);
|
||||||
isAllObject = isAllObject && Reflect.isObject(key);
|
isAllObject = isAllObject && Reflect.isObject(key);
|
||||||
isAllEnum = isAllEnum && Reflect.isEnumValue(key);
|
isAllEnum = isAllEnum && Reflect.isEnumValue(key);
|
||||||
keys.push(key);
|
keys.push(key);
|
||||||
@@ -490,19 +736,39 @@ class Interp {
|
|||||||
default: throw("=> expected");
|
default: throw("=> expected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isTypeMap) {
|
||||||
|
if(wantedType != null) {
|
||||||
|
isAllString = wantedType.match(CTPath(["Map"], [CTPath(["String"], _), _]));
|
||||||
|
isAllInt = wantedType.match(CTPath(["Map"], [CTPath(["Int"], _), _]));
|
||||||
|
if(isAllString || isAllInt) {
|
||||||
|
isAllObject = false;
|
||||||
|
isAllEnum = false;
|
||||||
|
} else {
|
||||||
|
if(!isAllObject && !isAllEnum) {
|
||||||
|
throw("Unknown Type Key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var map:Dynamic = {
|
var map:Dynamic = {
|
||||||
if (isAllInt) new haxe.ds.IntMap<Dynamic>();
|
if (isAllInt)
|
||||||
else if (isAllString) new haxe.ds.StringMap<Dynamic>();
|
new haxe.ds.IntMap<Dynamic>();
|
||||||
else if (isAllEnum) new haxe.ds.EnumValueMap<Dynamic, Dynamic>();
|
else if (isAllString)
|
||||||
else if (isAllObject) new haxe.ds.ObjectMap<Dynamic, Dynamic>();
|
new haxe.ds.StringMap<Dynamic>();
|
||||||
else throw 'Inconsistent key types';
|
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) {
|
for (n in 0...keys.length) {
|
||||||
setMapValue(map, keys[n], values[n]);
|
setMapValue(map, keys[n], values[n]);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var a = new Array();
|
var a = new Array();
|
||||||
for (e in arr) {
|
for (e in arr) {
|
||||||
a.push(expr(e));
|
a.push(expr(e));
|
||||||
@@ -514,8 +780,7 @@ class Interp {
|
|||||||
var index:Dynamic = expr(index);
|
var index:Dynamic = expr(index);
|
||||||
if (isMap(arr)) {
|
if (isMap(arr)) {
|
||||||
return getMapValue(arr, index);
|
return getMapValue(arr, index);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return arr[index];
|
return arr[index];
|
||||||
}
|
}
|
||||||
case ENew(cl, params):
|
case ENew(cl, params):
|
||||||
@@ -542,8 +807,8 @@ class Interp {
|
|||||||
restore(old);
|
restore(old);
|
||||||
inTry = oldTry;
|
inTry = oldTry;
|
||||||
// declare 'v'
|
// declare 'v'
|
||||||
declared.push({ n : n, old : locals.get(n) });
|
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||||
locals.set(n,{ r : err });
|
locals.set(n, {r: err, depth: depth});
|
||||||
var v:Dynamic = expr(ecatch);
|
var v:Dynamic = expr(ecatch);
|
||||||
restore(old);
|
restore(old);
|
||||||
return v;
|
return v;
|
||||||
@@ -572,7 +837,16 @@ class Interp {
|
|||||||
if (!match)
|
if (!match)
|
||||||
val = def == null ? null : expr(def);
|
val = def == null ? null : expr(def);
|
||||||
return val;
|
return val;
|
||||||
case EMeta(_, _, e):
|
case EMeta(a, b, e):
|
||||||
|
var oldAccessor = isBypassAccessor;
|
||||||
|
if(a == ":bypassAccessor") {
|
||||||
|
isBypassAccessor = true;
|
||||||
|
}
|
||||||
|
var val = expr(e);
|
||||||
|
|
||||||
|
isBypassAccessor = oldAccessor;
|
||||||
|
return val;
|
||||||
|
case ECheckType(e, _):
|
||||||
return expr(e);
|
return expr(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -586,12 +860,13 @@ class Interp {
|
|||||||
} catch (err:Stop) {
|
} catch (err:Stop) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case SContinue:
|
case SContinue:
|
||||||
case SBreak: break;
|
case SBreak:
|
||||||
case SReturn: throw err;
|
break;
|
||||||
|
case SReturn:
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (expr(econd) == true);
|
||||||
while( expr(econd) == true );
|
|
||||||
restore(old);
|
restore(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,8 +878,10 @@ class Interp {
|
|||||||
} catch (err:Stop) {
|
} catch (err:Stop) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case SContinue:
|
case SContinue:
|
||||||
case SBreak: break;
|
case SBreak:
|
||||||
case SReturn: throw err;
|
break;
|
||||||
|
case SReturn:
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,27 +890,33 @@ class Interp {
|
|||||||
|
|
||||||
function makeIterator(v:Dynamic):Iterator<Dynamic> {
|
function makeIterator(v:Dynamic):Iterator<Dynamic> {
|
||||||
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
|
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
|
||||||
if ( v.iterator != null ) v = v.iterator();
|
if (v.iterator != null)
|
||||||
|
v = v.iterator();
|
||||||
#else
|
#else
|
||||||
try v = v.iterator() catch( e : Dynamic ) {};
|
try
|
||||||
|
v = v.iterator()
|
||||||
|
catch (e:Dynamic) {};
|
||||||
#end
|
#end
|
||||||
if( v.hasNext == null || v.next == null ) error(EInvalidIterator(v));
|
if (v.hasNext == null || v.next == null)
|
||||||
|
error(EInvalidIterator(v));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
function forLoop(n, it, e) {
|
function forLoop(n, it, e) {
|
||||||
var old = declared.length;
|
var old = declared.length;
|
||||||
declared.push({ n : n, old : locals.get(n) });
|
declared.push({n: n, old: locals.get(n), depth: depth});
|
||||||
var it = makeIterator(expr(it));
|
var it = makeIterator(expr(it));
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
locals.set(n,{ r : it.next() });
|
locals.set(n, {r: it.next(), depth: depth});
|
||||||
try {
|
try {
|
||||||
expr(e);
|
expr(e);
|
||||||
} catch (err:Stop) {
|
} catch (err:Stop) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case SContinue:
|
case SContinue:
|
||||||
case SBreak: break;
|
case SBreak:
|
||||||
case SReturn: throw err;
|
break;
|
||||||
|
case SReturn:
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,7 +924,7 @@ class Interp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline function isMap(o:Dynamic):Bool {
|
inline function isMap(o:Dynamic):Bool {
|
||||||
return Std.is(o, haxe.Constraints.IMap);
|
return (o is IMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function getMapValue(map:Dynamic, key:Dynamic):Dynamic {
|
inline function getMapValue(map:Dynamic, key:Dynamic):Dynamic {
|
||||||
@@ -652,40 +935,89 @@ class Interp {
|
|||||||
cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).set(key, value);
|
cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).set(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static var getRedirects:Map<String, Dynamic->String->Dynamic> = [];
|
||||||
|
public static var setRedirects:Map<String, Dynamic->String->Dynamic->Dynamic> = [];
|
||||||
|
|
||||||
function get(o:Dynamic, f:String):Dynamic {
|
function get(o:Dynamic, f:String):Dynamic {
|
||||||
if ( o == null ) error(EInvalidAccess(f));
|
if (o == null)
|
||||||
|
error(EInvalidAccess(f));
|
||||||
return {
|
return {
|
||||||
#if php
|
var redirect:Dynamic->String->Dynamic = null;
|
||||||
// https://github.com/HaxeFoundation/haxe/issues/4915
|
var cls = Type.getClass(o);
|
||||||
try {
|
var cl:Null<String> = switch (Type.typeof(o)) {
|
||||||
Reflect.getProperty(o, f);
|
case TNull: "Null";
|
||||||
} catch (e:Dynamic) {
|
case TInt: "Int";
|
||||||
Reflect.field(o, f);
|
case TFloat: "Float";
|
||||||
|
case TBool: "Bool";
|
||||||
|
case _: cls != null ? Type.getClassName(cls) : null;
|
||||||
|
};
|
||||||
|
if (cl != null && getRedirects.exists(cl) && (redirect = getRedirects[cl]) != null) {
|
||||||
|
return redirect(o, f);
|
||||||
|
} else if (o is IHScriptCustomBehaviour) {
|
||||||
|
var obj = cast(o, IHScriptCustomBehaviour);
|
||||||
|
return obj.hget(f);
|
||||||
|
} else {
|
||||||
|
var v = null;
|
||||||
|
if(isBypassAccessor) {
|
||||||
|
if ((v = Reflect.field(o, f)) == null)
|
||||||
|
v = Reflect.field(cls, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(v == null) {
|
||||||
|
if ((v = Reflect.getProperty(o, f)) == null)
|
||||||
|
v = Reflect.getProperty(cls, f);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
Reflect.getProperty(o, f);
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function set(o:Dynamic, f:String, v:Dynamic):Dynamic {
|
function set(o:Dynamic, f:String, v:Dynamic):Dynamic {
|
||||||
if( o == null ) error(EInvalidAccess(f));
|
if (o == null)
|
||||||
|
error(EInvalidAccess(f));
|
||||||
|
|
||||||
|
var redirect:Dynamic->String->Dynamic->Dynamic = null;
|
||||||
|
var cls = Type.getClass(o);
|
||||||
|
var cl:Null<String> = switch (Type.typeof(o)) {
|
||||||
|
case TNull: "Null";
|
||||||
|
case TInt: "Int";
|
||||||
|
case TFloat: "Float";
|
||||||
|
case TBool: "Bool";
|
||||||
|
case _: cls != null ? Type.getClassName(cls) : null;
|
||||||
|
};
|
||||||
|
if (cl != null && setRedirects.exists(cl) && (redirect = setRedirects[cl]) != null)
|
||||||
|
return redirect(o, f, v);
|
||||||
|
else if (o is IHScriptCustomBehaviour) {
|
||||||
|
var obj = cast(o, IHScriptCustomBehaviour);
|
||||||
|
return obj.hset(f, v);
|
||||||
|
}
|
||||||
|
if(isBypassAccessor) {
|
||||||
|
Reflect.setField(o, f, v);
|
||||||
|
} else {
|
||||||
Reflect.setProperty(o, f, v);
|
Reflect.setProperty(o, f, v);
|
||||||
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fcall(o:Dynamic, f:String, args:Array<Dynamic>):Dynamic {
|
function fcall(o:Dynamic, f:String, args:Array<Dynamic>):Dynamic {
|
||||||
|
if(o == CustomClassHandler.staticHandler && scriptObject != null) {
|
||||||
|
return Reflect.callMethod(scriptObject, Reflect.field(scriptObject, "_HX_SUPER__" + f), args);
|
||||||
|
}
|
||||||
return call(o, get(o, f), args);
|
return call(o, get(o, f), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
function call(o:Dynamic, f:Dynamic, args:Array<Dynamic>):Dynamic {
|
function call(o:Dynamic, f:Dynamic, args:Array<Dynamic>):Dynamic {
|
||||||
|
if(f == CustomClassHandler.staticHandler) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return Reflect.callMethod(o, f, args);
|
return Reflect.callMethod(o, f, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cnew(cl:String, args:Array<Dynamic>):Dynamic {
|
function cnew(cl:String, args:Array<Dynamic>):Dynamic {
|
||||||
var c = Type.resolveClass(cl);
|
var cl:String = cast cl;
|
||||||
if( c == null ) c = resolve(cl);
|
var c:Dynamic = resolve(cl);
|
||||||
return Type.createInstance(c,args);
|
if (c == null)
|
||||||
|
c = Type.resolveClass(cl);
|
||||||
|
return (c is IHScriptCustomConstructor) ? cast(c, IHScriptCustomConstructor).hnew(args) : Type.createInstance(c, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+15
-1
@@ -79,6 +79,8 @@ class Macro {
|
|||||||
#if (haxe_ver >= 4)
|
#if (haxe_ver >= 4)
|
||||||
case OpIn: "in";
|
case OpIn: "in";
|
||||||
#end
|
#end
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
};
|
};
|
||||||
binops.set(str, op);
|
binops.set(str, op);
|
||||||
if( assign )
|
if( assign )
|
||||||
@@ -92,6 +94,9 @@ class Macro {
|
|||||||
case OpNegBits: "~";
|
case OpNegBits: "~";
|
||||||
case OpIncrement: "++";
|
case OpIncrement: "++";
|
||||||
case OpDecrement: "--";
|
case OpDecrement: "--";
|
||||||
|
#if (haxe_ver >= 4.2)
|
||||||
|
case OpSpread: continue;
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
unops.set(str, op);
|
unops.set(str, op);
|
||||||
}
|
}
|
||||||
@@ -113,6 +118,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 +133,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 +219,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 +250,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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+592
-115
File diff suppressed because it is too large
Load Diff
+49
-6
@@ -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 -> ");
|
||||||
@@ -98,6 +114,25 @@ class Printer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch( #if hscriptPos e.e #else e #end ) {
|
switch( #if hscriptPos e.e #else e #end ) {
|
||||||
|
case EImport(c, n):
|
||||||
|
add("import " + c);
|
||||||
|
if(n != null)
|
||||||
|
add(' as $n');
|
||||||
|
case EClass(name, fields, extend, interfaces):
|
||||||
|
add('class $name');
|
||||||
|
if (extend != null)
|
||||||
|
add(' extends $extend');
|
||||||
|
for(_interface in interfaces) {
|
||||||
|
add(' implements $_interface');
|
||||||
|
}
|
||||||
|
add(' {\n');
|
||||||
|
tabs += "\t";
|
||||||
|
//for(field in fields) {
|
||||||
|
// expr(field);
|
||||||
|
//}
|
||||||
|
|
||||||
|
tabs = tabs.substr(1);
|
||||||
|
add("}");
|
||||||
case EConst(c):
|
case EConst(c):
|
||||||
switch( c ) {
|
switch( c ) {
|
||||||
case CInt(i): add(i);
|
case CInt(i): add(i);
|
||||||
@@ -106,7 +141,7 @@ class Printer {
|
|||||||
}
|
}
|
||||||
case EIdent(v):
|
case EIdent(v):
|
||||||
add(v);
|
add(v);
|
||||||
case EVar(n, t, e):
|
case EVar(n, t, e): // TODO: static, public, override
|
||||||
add("var " + n);
|
add("var " + n);
|
||||||
addType(t);
|
addType(t);
|
||||||
if( e != null ) {
|
if( e != null ) {
|
||||||
@@ -129,9 +164,9 @@ class Printer {
|
|||||||
tabs = tabs.substr(1);
|
tabs = tabs.substr(1);
|
||||||
add("}");
|
add("}");
|
||||||
}
|
}
|
||||||
case EField(e, f):
|
case EField(e, f, s):
|
||||||
expr(e);
|
expr(e);
|
||||||
add("." + f);
|
add((s == true ? "?." : ".") + f);
|
||||||
case EBinop(op, e1, e2):
|
case EBinop(op, e1, e2):
|
||||||
expr(e1);
|
expr(e1);
|
||||||
add(" " + op + " ");
|
add(" " + op + " ");
|
||||||
@@ -191,7 +226,7 @@ class Printer {
|
|||||||
add("break");
|
add("break");
|
||||||
case EContinue:
|
case EContinue:
|
||||||
add("continue");
|
add("continue");
|
||||||
case EFunction(params, e, name, ret):
|
case EFunction(params, e, name, ret): // TODO: static, public, override
|
||||||
add("function");
|
add("function");
|
||||||
if( name != null )
|
if( name != null )
|
||||||
add(" " + name);
|
add(" " + name);
|
||||||
@@ -218,7 +253,7 @@ class Printer {
|
|||||||
add("[");
|
add("[");
|
||||||
expr(index);
|
expr(index);
|
||||||
add("]");
|
add("]");
|
||||||
case EArrayDecl(el):
|
case EArrayDecl(el, _):
|
||||||
add("[");
|
add("[");
|
||||||
var first = true;
|
var first = true;
|
||||||
for( e in el ) {
|
for( e in el ) {
|
||||||
@@ -300,6 +335,12 @@ class Printer {
|
|||||||
}
|
}
|
||||||
add(" ");
|
add(" ");
|
||||||
expr(e);
|
expr(e);
|
||||||
|
case ECheckType(e, t):
|
||||||
|
add("(");
|
||||||
|
expr(e);
|
||||||
|
add(" : ");
|
||||||
|
addType(t);
|
||||||
|
add(")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +350,7 @@ class Printer {
|
|||||||
|
|
||||||
public static function errorToString( e : Expr.Error ) {
|
public static function errorToString( e : Expr.Error ) {
|
||||||
var message = switch( #if hscriptPos e.e #else e #end ) {
|
var message = switch( #if hscriptPos e.e #else e #end ) {
|
||||||
case EInvalidChar(c): "Invalid character: '"+String.fromCharCode(c)+"' ("+c+")";
|
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF (End Of File)" : String.fromCharCode(c))+"' ("+c+")";
|
||||||
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
||||||
case EUnterminatedString: "Unterminated string";
|
case EUnterminatedString: "Unterminated string";
|
||||||
case EUnterminatedComment: "Unterminated comment";
|
case EUnterminatedComment: "Unterminated comment";
|
||||||
@@ -319,6 +360,8 @@ class Printer {
|
|||||||
case EInvalidOp(op): "Invalid operator: "+op;
|
case EInvalidOp(op): "Invalid operator: "+op;
|
||||||
case EInvalidAccess(f): "Invalid access to field " + f;
|
case EInvalidAccess(f): "Invalid access to field " + f;
|
||||||
case ECustom(msg): msg;
|
case ECustom(msg): msg;
|
||||||
|
case EInvalidClass(cla): "Invalid class: " + cla + " was not found.";
|
||||||
|
case EAlreadyExistingClass(cla): 'Custom Class named $cla already exists.';
|
||||||
};
|
};
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
return e.origin + ":" + e.line + ": " + message;
|
return e.origin + ":" + e.line + ": " + message;
|
||||||
|
|||||||
+25
-8
@@ -25,8 +25,10 @@ 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 EImport(c): f(e);
|
||||||
|
case EClass(_, e, _, _): for( a in e ) f(a);
|
||||||
case EVar(_, _, e): if( e != null ) f(e);
|
case EVar(_, _, e): if( e != null ) f(e);
|
||||||
case EParent(e): f(e);
|
case EParent(e): f(e);
|
||||||
case EBlock(el): for( e in el ) f(e);
|
case EBlock(el): for( e in el ) f(e);
|
||||||
@@ -56,16 +58,14 @@ 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 +88,26 @@ 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);
|
||||||
|
case EImport(c): EImport(c);
|
||||||
|
case EClass(name, el, extend, interfaces): EClass(name, [for( e in el ) f(e)], extend, interfaces);
|
||||||
}
|
}
|
||||||
|
return mk(edef, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
package hscript;
|
||||||
|
|
||||||
|
import Type.ValueType;
|
||||||
|
import haxe.macro.ComplexTypeTools;
|
||||||
|
#if macro
|
||||||
|
import haxe.macro.Expr;
|
||||||
|
import haxe.macro.Context;
|
||||||
|
import haxe.macro.Printer;
|
||||||
|
import haxe.macro.Compiler;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class UsingHandler {
|
||||||
|
public var usedClass:Class<Dynamic>;
|
||||||
|
public var className:String;
|
||||||
|
|
||||||
|
public function new(className:String, usedClass:Class<Dynamic>) {
|
||||||
|
this.className = className;
|
||||||
|
this.usedClass = usedClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function init() {
|
||||||
|
Compiler.addGlobalMetadata('flixel', '@:build(hscript.UsingHandler.build())');
|
||||||
|
Compiler.addGlobalMetadata('openfl.display.BlendMode', '@:build(hscript.UsingHandler.build())');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function build():Array<Field> {
|
||||||
|
var fields = Context.getBuildFields();
|
||||||
|
var clRef = Context.getLocalClass();
|
||||||
|
if (clRef == null) return fields;
|
||||||
|
var cl = clRef.get();
|
||||||
|
|
||||||
|
if (/* cl.name.startsWith("Flx") && */ cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType")) {
|
||||||
|
var metas = cl.meta.get();
|
||||||
|
|
||||||
|
var shadowClass = macro class {
|
||||||
|
|
||||||
|
};
|
||||||
|
shadowClass.kind = TDClass();
|
||||||
|
shadowClass.params = switch(cl.params.length) {
|
||||||
|
case 0:
|
||||||
|
null;
|
||||||
|
case 1:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: "T",
|
||||||
|
}
|
||||||
|
];
|
||||||
|
default:
|
||||||
|
[for(k=>e in cl.params) {
|
||||||
|
name: "T" + Std.int(k+1)
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
shadowClass.name = '${cl.name.substr(0, cl.name.length - 6)}_HSC';
|
||||||
|
|
||||||
|
var imports = Context.getLocalImports().copy();
|
||||||
|
setupMetas(shadowClass, imports);
|
||||||
|
|
||||||
|
for(f in fields)
|
||||||
|
switch(f.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (f.access.contains(AStatic)) {
|
||||||
|
if (fun.expr != null)
|
||||||
|
shadowClass.fields.push(f);
|
||||||
|
}
|
||||||
|
case FProp(get, set, t, e):
|
||||||
|
if (get == "default" && (set == "never" || set == "null"))
|
||||||
|
shadowClass.fields.push(f);
|
||||||
|
case FVar(t, e):
|
||||||
|
if (f.access.contains(AStatic) || cl.meta.has(":enum") || f.name.toUpperCase() == f.name) {
|
||||||
|
var name:String = f.name;
|
||||||
|
var enumType:String = cl.name;
|
||||||
|
var pack = cl.module.split(".");
|
||||||
|
pack.pop();
|
||||||
|
var complexType:ComplexType = t != null ? t : (name.contains("REGEX") ? TPath({
|
||||||
|
name: "EReg",
|
||||||
|
pack: []
|
||||||
|
}) : TPath({
|
||||||
|
name: cl.name.substr(0, cl.name.length - 6),
|
||||||
|
pack: pack}));
|
||||||
|
var field:Field = {
|
||||||
|
pos: f.pos,
|
||||||
|
name: f.name,
|
||||||
|
meta: f.meta,
|
||||||
|
kind: FVar(complexType, {
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
expr: ECast(e, complexType)
|
||||||
|
}),
|
||||||
|
doc: f.doc,
|
||||||
|
access: [APublic, AStatic]
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowClass.fields.push(field);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.defineModule(cl.module + "_HSC", [shadowClass], imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function fixStdTypes(type:ComplexType) {
|
||||||
|
switch(type) {
|
||||||
|
case TPath({name: "StdTypes"}):
|
||||||
|
var a:TypePath = type.getParameters()[0];
|
||||||
|
a.name = a.sub;
|
||||||
|
a.sub = null;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function setupMetas(shadowClass:TypeDefinition, imports) {
|
||||||
|
shadowClass.meta = [{
|
||||||
|
name: ':dox',
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
expr: EConst(CIdent("hide")),
|
||||||
|
pos: Context.currentPos()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
var module = Context.getModule(Context.getLocalModule());
|
||||||
|
for(t in module) {
|
||||||
|
switch(t) {
|
||||||
|
case TInst(t, params):
|
||||||
|
if (t != null) {
|
||||||
|
var e = t.get();
|
||||||
|
processModule(shadowClass, e.module, e.name);
|
||||||
|
processImport(imports, e.module, e.name);
|
||||||
|
}
|
||||||
|
case TEnum(t, params):
|
||||||
|
if (t != null) {
|
||||||
|
var e = t.get();
|
||||||
|
processModule(shadowClass, e.module, e.name);
|
||||||
|
processImport(imports, e.module, e.name);
|
||||||
|
}
|
||||||
|
case TType(t, params):
|
||||||
|
if (t != null) {
|
||||||
|
var e = t.get();
|
||||||
|
processModule(shadowClass, e.module, e.name);
|
||||||
|
processImport(imports, e.module, e.name);
|
||||||
|
}
|
||||||
|
case TAbstract(t, params):
|
||||||
|
if (t != null) {
|
||||||
|
var e = t.get();
|
||||||
|
processModule(shadowClass, e.module, e.name);
|
||||||
|
processImport(imports, e.module, e.name);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// not needed?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function processModule(shadowClass:TypeDefinition, module:String, n:String) {
|
||||||
|
if (n.endsWith("_Impl_"))
|
||||||
|
n = n.substr(0, n.length - 6);
|
||||||
|
if (module.endsWith("_Impl_"))
|
||||||
|
module = module.substr(0, module.length - 6);
|
||||||
|
|
||||||
|
shadowClass.meta.push(
|
||||||
|
{
|
||||||
|
name: ':access',
|
||||||
|
params: [
|
||||||
|
Context.parse(fixModuleName(module.endsWith('.${n}') ? module : '${module}.${n}'), Context.currentPos())
|
||||||
|
],
|
||||||
|
pos: Context.currentPos()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*public static function getModuleName(path:Type) {
|
||||||
|
switch(path) {
|
||||||
|
case TPath(name, pack):// | TDClass(name, pack):
|
||||||
|
var str = "";
|
||||||
|
for(p in pack) {
|
||||||
|
str += p + ".";
|
||||||
|
}
|
||||||
|
str += name;
|
||||||
|
return str;
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return "INVALID";
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public static function fixModuleName(name:String) {
|
||||||
|
return [for(s in name.split(".")) if (s.charAt(0) == "_") s.substr(1) else s].join(".");
|
||||||
|
}
|
||||||
|
public static function processImport(imports:Array<ImportExpr>, module:String, n:String) {
|
||||||
|
if (n.endsWith("_Impl_"))
|
||||||
|
n = n.substr(0, n.length - 6);
|
||||||
|
module = fixModuleName(module);
|
||||||
|
if (module.endsWith("_Impl_"))
|
||||||
|
module = module.substr(0, module.length - 6);
|
||||||
|
|
||||||
|
imports.push({
|
||||||
|
path: [for(m in module.split(".")) {
|
||||||
|
name: m,
|
||||||
|
pos: Context.currentPos()
|
||||||
|
}],
|
||||||
|
mode: INormal
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function cleanExpr(expr:Expr, oldFunc:String, newFunc:String) {
|
||||||
|
if (expr == null) return;
|
||||||
|
if (expr.expr == null) return;
|
||||||
|
switch(expr.expr) {
|
||||||
|
case EConst(c):
|
||||||
|
switch(c) {
|
||||||
|
case CIdent(s):
|
||||||
|
if (s == oldFunc)
|
||||||
|
expr.expr = EConst(CIdent(newFunc));
|
||||||
|
case CString(s, b):
|
||||||
|
if (s == oldFunc)
|
||||||
|
expr.expr = EConst(CString(s, b));
|
||||||
|
default:
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
case EField(e, field):
|
||||||
|
if (field == oldFunc && e != null) {
|
||||||
|
switch(e.expr) {
|
||||||
|
case EConst(c):
|
||||||
|
switch(c) {
|
||||||
|
case CIdent(s):
|
||||||
|
if (s == "super")
|
||||||
|
expr.expr = EField(e, newFunc);
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case EParenthesis(e):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case EObjectDecl(fields):
|
||||||
|
for(f in fields) {
|
||||||
|
cleanExpr(f.expr, oldFunc, newFunc);
|
||||||
|
}
|
||||||
|
case EArrayDecl(values):
|
||||||
|
for(a in values) {
|
||||||
|
cleanExpr(a, oldFunc, newFunc);
|
||||||
|
}
|
||||||
|
case ECall(e, params):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case EBlock(exprs):
|
||||||
|
for(e in exprs)
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case EFor(it, expr):
|
||||||
|
cleanExpr(it, oldFunc, newFunc);
|
||||||
|
cleanExpr(expr, oldFunc, newFunc);
|
||||||
|
case EIf(econd, eif, eelse):
|
||||||
|
cleanExpr(econd, oldFunc, newFunc);
|
||||||
|
cleanExpr(eif, oldFunc, newFunc);
|
||||||
|
cleanExpr(eelse, oldFunc, newFunc);
|
||||||
|
case EWhile(econd, e, normalWhile):
|
||||||
|
cleanExpr(econd, oldFunc, newFunc);
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case ECast(e, t):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case ECheckType(e, t):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case ETry(e, catches):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
for(c in catches) {
|
||||||
|
cleanExpr(c.expr, oldFunc, newFunc);
|
||||||
|
}
|
||||||
|
case EThrow(e):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case ETernary(econd, eif, eelse):
|
||||||
|
cleanExpr(econd, oldFunc, newFunc);
|
||||||
|
cleanExpr(eif, oldFunc, newFunc);
|
||||||
|
cleanExpr(eelse, oldFunc, newFunc);
|
||||||
|
case ESwitch(e, cases, edef):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
for(c in cases) {
|
||||||
|
cleanExpr(c.expr, oldFunc, newFunc);
|
||||||
|
}
|
||||||
|
cleanExpr(edef, oldFunc, newFunc);
|
||||||
|
case EReturn(e):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case EIs(e, t):
|
||||||
|
cleanExpr(e, oldFunc, newFunc);
|
||||||
|
case EVars(vars):
|
||||||
|
for(v in vars) {
|
||||||
|
cleanExpr(v.expr, oldFunc, newFunc);
|
||||||
|
}
|
||||||
|
case ENew(t, params):
|
||||||
|
for(p in params) {
|
||||||
|
cleanExpr(p, oldFunc, newFunc);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
class UsingHandler {
|
||||||
|
public var usedClass:Class<Dynamic>;
|
||||||
|
public var className:String;
|
||||||
|
}
|
||||||
|
#end
|
||||||
@@ -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