Compare commits
214
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49c90e6434 | ||
|
|
bb46d45d56 | ||
|
|
3a5c4f2164 | ||
|
|
f18c7a2210 | ||
|
|
123a7de64a | ||
|
|
e0e1436930 | ||
|
|
b96e6c8149 | ||
|
|
f6402ac638 | ||
|
|
1e55d0200b | ||
|
|
1725dfd1ea | ||
|
|
a8cc0ccc86 | ||
|
|
7dd868aac7 | ||
|
|
220e5ce007 | ||
|
|
80f6ea4502 | ||
|
|
eb820aaf6a | ||
|
|
a754c162d9 | ||
|
|
de18ceb887 | ||
|
|
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 | ||
|
|
70b11ec7ad | ||
|
|
f2944e0bae | ||
|
|
fdec33d086 | ||
|
|
0702074469 | ||
|
|
6d5cbf6974 | ||
|
|
5429a3a4d4 | ||
|
|
c124076279 | ||
|
|
0d1d811d2c | ||
|
|
8c04831339 | ||
|
|
4a8b2690aa | ||
|
|
e2bc716ea7 | ||
|
|
6c5987f9af | ||
|
|
1e79880c72 | ||
|
|
f62d891c63 | ||
|
|
930cb8853c | ||
|
|
22104ff64e | ||
|
|
17564441b5 | ||
|
|
a9140a4403 | ||
|
|
ce47ca0a8a | ||
|
|
852fee170e | ||
|
|
8463e99d13 | ||
|
|
3c016b73ee | ||
|
|
8d4173b0be | ||
|
|
502f043804 | ||
|
|
f8571fb175 | ||
|
|
7209aa8880 | ||
|
|
1a4a1217ae | ||
|
|
139c360feb | ||
|
|
be1afbdb5c | ||
|
|
8a7e8c8d7d | ||
|
|
931f79dacb | ||
|
|
261e6ee78e | ||
|
|
9eaddcdafb | ||
|
|
b8ede1a3e7 | ||
|
|
bbaacd5d28 | ||
|
|
60ed5fdfe2 | ||
|
|
512f88c63e | ||
|
|
50c01b2cfb | ||
|
|
27d3f889b5 | ||
|
|
140a9918c0 | ||
|
|
fc6a30b684 | ||
|
|
deb0ae8b8e | ||
|
|
1425479569 | ||
|
|
09923651d8 | ||
|
|
7ca5b85051 | ||
|
|
a34faf8a26 | ||
|
|
7708159e92 | ||
|
|
7851d48e82 | ||
|
|
f320b4fa9b | ||
|
|
b3ea81f4e8 |
@@ -1,2 +1,4 @@
|
|||||||
/hscript.swf
|
/hscript.swf
|
||||||
/release.zip
|
/release.zip
|
||||||
|
|
||||||
|
tests/bin/*
|
||||||
+18
-24
@@ -4,10 +4,11 @@ os:
|
|||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
|
|
||||||
osx_image: xcode6.4
|
dist: bionic
|
||||||
|
|
||||||
haxe:
|
haxe:
|
||||||
- "3.2.1"
|
- "3.4.7"
|
||||||
|
- "4.0.3"
|
||||||
- development
|
- development
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
@@ -19,44 +20,34 @@ addons:
|
|||||||
# Python
|
# Python
|
||||||
- python3
|
- python3
|
||||||
# PHP
|
# PHP
|
||||||
- php5-cli
|
- php-cli
|
||||||
|
- php-mbstring
|
||||||
# C#
|
# C#
|
||||||
- mono-devel
|
- mono-devel
|
||||||
- mono-mcs
|
- mono-mcs
|
||||||
# Flash
|
|
||||||
- libcurl3:i386
|
|
||||||
- libglib2.0-0:i386
|
|
||||||
- libx11-6:i386
|
|
||||||
- libxext6:i386
|
|
||||||
- libxt6:i386
|
|
||||||
- libxcursor1:i386
|
|
||||||
- libnss3:i386
|
|
||||||
- libgtk2.0-0:i386
|
|
||||||
|
|
||||||
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;
|
|
||||||
elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
|
||||||
brew update;
|
brew update;
|
||||||
brew install mono;
|
brew install mono;
|
||||||
brew install python3;
|
brew install php;
|
||||||
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
|
||||||
|
- haxelib install hx3compat
|
||||||
- haxelib dev hscript .
|
- haxelib dev hscript .
|
||||||
- haxelib list
|
- haxelib list
|
||||||
|
|
||||||
@@ -65,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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (C)2008-2017 Haxe Foundation
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
@@ -1,8 +1,18 @@
|
|||||||
hscript
|
hscript-improved
|
||||||
=======
|
=======
|
||||||
|
|
||||||
[](https://travis-ci.org/HaxeFoundation/hscript)
|
How to install
|
||||||
[](https://ci.appveyor.com/project/HaxeFoundation/hscript)
|
```
|
||||||
|
haxelib git hscript-improved https://github.com/FNF-CNE-Devs/hscript-improved.git
|
||||||
|
```
|
||||||
|
|
||||||
|
To enable custom classes support you have to do this in project.xml
|
||||||
|
```xml
|
||||||
|
<define name="CUSTOM_CLASSES" />
|
||||||
|
```
|
||||||
|
Warning: custom classes are sometimes broken, would like help to fix them. You can only override functions from the current class, not from the extended part, like you cant override update in FlxText because FlxText doesnt have a update function overriden
|
||||||
|
|
||||||
|
-----------
|
||||||
|
|
||||||
Parse and evalutate Haxe expressions.
|
Parse and evalutate Haxe expressions.
|
||||||
|
|
||||||
@@ -64,26 +74,40 @@ You can use `parser.allowJSON` to allow JSON data.
|
|||||||
|
|
||||||
You can use `parser.allowTypes` to parse types for local vars, exceptions, function args and return types. Types are ignored by the interpreter.
|
You can use `parser.allowTypes` to parse types for local vars, exceptions, function args and return types. Types are ignored by the interpreter.
|
||||||
|
|
||||||
|
You can use `parser.allowMetadata` to parse metadata before expressions on in anonymous types. Metadata are ignored by the interpreter.
|
||||||
|
|
||||||
You can use `new hscript.Macro(pos).convert(ast)` to convert an hscript AST to a Haxe macros one.
|
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)
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import haxe.ds.EnumValueMap;
|
import haxe.ds.EnumValueMap;
|
||||||
import haxe.ds.Option;
|
import haxe.ds.Option;
|
||||||
import hscript.Macro;
|
import hscript.Macro;
|
||||||
|
import hscript.Tools;
|
||||||
|
import hscript.Async;
|
||||||
|
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);
|
||||||
@@ -15,14 +19,21 @@ 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 {
|
||||||
assertScript("0",0);
|
assertScript("0",0);
|
||||||
assertScript("0xFF", 255);
|
assertScript("0xFF", 255);
|
||||||
assertScript("0xBFFFFFFF", 0xBFFFFFFF);
|
#if !(php || python)
|
||||||
assertScript("0x7FFFFFFF", 0x7FFFFFFF);
|
#if haxe3
|
||||||
|
assertScript("0xBFFFFFFF", 0xBFFFFFFF);
|
||||||
|
assertScript("0x7FFFFFFF", 0x7FFFFFFF);
|
||||||
|
#elseif !neko
|
||||||
|
assertScript("n(0xBFFFFFFF)", 0xBFFFFFFF, { n : haxe.Int32.toNativeInt });
|
||||||
|
assertScript("n(0x7FFFFFFF)", 0x7FFFFFFF, { n : haxe.Int32.toNativeInt } );
|
||||||
|
#end
|
||||||
|
#end
|
||||||
assertScript("-123",-123);
|
assertScript("-123",-123);
|
||||||
assertScript("- 123",-123);
|
assertScript("- 123",-123);
|
||||||
assertScript("1.546",1.546);
|
assertScript("1.546",1.546);
|
||||||
@@ -89,8 +100,21 @@ 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 {
|
||||||
var objKey = { ok:true };
|
var objKey = { ok:true };
|
||||||
var vars = {
|
var vars = {
|
||||||
@@ -103,7 +127,7 @@ class Test extends TestCase {
|
|||||||
stringIntMap: ["foo" => 100]
|
stringIntMap: ["foo" => 100]
|
||||||
}
|
}
|
||||||
vars.enumMap.set(vars.enumKey, "ok");
|
vars.enumMap.set(vars.enumKey, "ok");
|
||||||
|
|
||||||
assertScript('stringMap["foo"]', "Foo", vars);
|
assertScript('stringMap["foo"]', "Foo", vars);
|
||||||
assertScript('intMap[100]', "one hundred", vars);
|
assertScript('intMap[100]', "one hundred", vars);
|
||||||
assertScript('objMap[objKey]', "ok", vars);
|
assertScript('objMap[objKey]', "ok", vars);
|
||||||
@@ -142,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
|
||||||
+7
-10
@@ -5,20 +5,19 @@ 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.2.1 -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
|
|
||||||
- cinst php -y
|
|
||||||
# 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
|
||||||
- haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1
|
- haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1
|
||||||
|
- haxelib install hx3compat > log.txt || type log.txt && cmd /C exit 1
|
||||||
- haxelib dev hscript .
|
- haxelib dev hscript .
|
||||||
- haxelib list
|
- haxelib list
|
||||||
|
|
||||||
@@ -34,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 && C:\tools\php\php.exe 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
|
||||||
+2
-1
@@ -1,2 +1,3 @@
|
|||||||
-main Test
|
-main TestHScript
|
||||||
-dce no
|
-dce no
|
||||||
|
-lib hx3compat
|
||||||
+3
-1
@@ -1 +1,3 @@
|
|||||||
--macro keep('IntIterator')
|
--macro keep('IntIterator')
|
||||||
|
--macro hscript.macros.UsingHandler.init()
|
||||||
|
--macro hscript.macros.ClassExtendMacro.init()
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
*.exe
|
|
||||||
*.app
|
|
||||||
flashplayerdebugger
|
|
||||||
@@ -1,91 +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":
|
|
||||||
"https://fpdownload.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.i386.tar.gz";
|
|
||||||
case "Mac":
|
|
||||||
"https://fpdownload.macromedia.com/pub/flashplayer/updaters/21/flashplayer_21_sa_debug.dmg";
|
|
||||||
case "Windows":
|
|
||||||
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/21/flashplayer_21_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":
|
|
||||||
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 _:
|
|
||||||
neko.Lib.rethrow(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +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 8 times, it should succeed one of those...
|
|
||||||
var c = -1;
|
|
||||||
for (i in 0...8) {
|
|
||||||
if ((c = command("xvfb-run", ["flash/flashplayerdebugger", swf])) == 0)
|
|
||||||
break;
|
|
||||||
println('retry... (${i+1})');
|
|
||||||
}
|
|
||||||
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
|
|
||||||
+9
-9
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "hscript",
|
"name": "hscript",
|
||||||
"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.0.7",
|
"version": "2.4.0",
|
||||||
"releasenote": "fixes for haxe 3.3, use property access by default",
|
"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>
|
|
||||||
@@ -0,0 +1,536 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package hscript;
|
||||||
|
import hscript.Expr;
|
||||||
|
|
||||||
|
|
||||||
|
enum VarMode {
|
||||||
|
Defined;
|
||||||
|
ForceSync;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Async {
|
||||||
|
|
||||||
|
var definedVars : Array<{ n : String, prev : Null<VarMode> }>;
|
||||||
|
var vars : Map<String,VarMode>;
|
||||||
|
var currentFun : String;
|
||||||
|
var currentLoop : Expr;
|
||||||
|
var currentBreak : Expr -> Expr;
|
||||||
|
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 nullId = mk(EIdent("null"), nullExpr);
|
||||||
|
|
||||||
|
inline static function expr( e : Expr ) {
|
||||||
|
return #if hscriptPos e.e #else e #end;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static function mk( e, inf : Expr ) : Expr {
|
||||||
|
return #if hscriptPos { e : e, pmin : inf.pmin, pmax : inf.pmax, origin : inf.origin, line : inf.line } #else e #end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert a script into asynchronous one.
|
||||||
|
- calls such as foo(a,b,c) are translated to a_foo(function(r) ...rest, a,b,c) where r is the result value
|
||||||
|
- object access such obj.bar(a,b,c) are translated to obj.a_bar(function(r) ...rest, a, b, c)
|
||||||
|
- @async expr will execute the expression but continue without waiting for it to finish
|
||||||
|
- @split [ e1, e2, e3 ] is transformed to split(function(_) ...rest, [e1, e2, e3]) which
|
||||||
|
should execute asynchronously all expressions - until they return - before continuing the execution
|
||||||
|
- for(i in v) block; loops are translated to the following:
|
||||||
|
var _i = makeIterator(v);
|
||||||
|
function _loop() {
|
||||||
|
if( !_i.hasNext() ) return;
|
||||||
|
var v = _i.next();
|
||||||
|
block(function(_) _loop());
|
||||||
|
}
|
||||||
|
_loop()
|
||||||
|
- while loops are translated similar to for loops
|
||||||
|
- break and continue are correctly handled
|
||||||
|
- you can use @sync <expr> to disable async transformation in some code parts (for performance reason)
|
||||||
|
- a few expressions are still not supported (complex calls, try/catch, and a few others)
|
||||||
|
|
||||||
|
In these examples ...rest represents the continuation of execution of the script after the expression
|
||||||
|
**/
|
||||||
|
public static function toAsync( e : Expr, topLevelSync = false ) {
|
||||||
|
var a = new Async();
|
||||||
|
return a.build(e, topLevelSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
public dynamic function getTopLevelEnd() {
|
||||||
|
return ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function build( e : Expr, topLevelSync = false ) {
|
||||||
|
if( topLevelSync ) {
|
||||||
|
return buildSync(e,null);
|
||||||
|
} else {
|
||||||
|
var end = getTopLevelEnd();
|
||||||
|
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 {
|
||||||
|
switch( expr(e) ) {
|
||||||
|
case EFunction(_,_,name,_):
|
||||||
|
if( name != null )
|
||||||
|
return toCps(e, null, null);
|
||||||
|
return e;
|
||||||
|
case EBlock(el):
|
||||||
|
var v = saveVars();
|
||||||
|
lookupFunctions(el);
|
||||||
|
var e = block([for(e in el) buildSync(e,exit)], e);
|
||||||
|
restoreVars(v);
|
||||||
|
return e;
|
||||||
|
case EMeta("async", _, e):
|
||||||
|
return toCps(e, ignore(), ignore());
|
||||||
|
case 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 ):
|
||||||
|
return currentBreak(e);
|
||||||
|
case EContinue if( currentLoop != null ):
|
||||||
|
return block([retNull(currentLoop, e), mk(EReturn(),e)],e);
|
||||||
|
case EFor(_), EWhile(_):
|
||||||
|
var oldLoop = currentLoop, oldBreak = currentBreak;
|
||||||
|
currentLoop = null;
|
||||||
|
currentBreak = null;
|
||||||
|
e = Tools.map(e, buildSync.bind(_, exit));
|
||||||
|
currentLoop = oldLoop;
|
||||||
|
currentBreak = oldBreak;
|
||||||
|
return e;
|
||||||
|
case EReturn(eret) if( exit != null ):
|
||||||
|
return block([eret == null ? retNull(exit, e) : call(exit,[eret], e), mk(EReturn(),e)], e);
|
||||||
|
default:
|
||||||
|
return Tools.map(e, buildSync.bind(_, exit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
vars = new Map();
|
||||||
|
definedVars = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function ignore(?e) : Expr {
|
||||||
|
var inf = e == null ? nullExpr : e;
|
||||||
|
return fun("_", block(e == null ? [] : [e],inf));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function ident(str, e) {
|
||||||
|
return mk(EIdent(str), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function fun(arg:String, e, ?name) {
|
||||||
|
return mk(EFunction([{ name : arg, t : null }], e, name), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function funs(arg:Array<String>, e, ?name) {
|
||||||
|
return mk(EFunction([for( a in arg ) { name : a, t : null }], e, name), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function block(arr:Array<Expr>, e) {
|
||||||
|
if( arr.length == 1 && expr(arr[0]).match(EBlock(_)) )
|
||||||
|
return arr[0];
|
||||||
|
return mk(EBlock(arr), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function field(e, f, inf) {
|
||||||
|
return mk(EField(e, f), inf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function binop(op, e1, e2, inf) {
|
||||||
|
return mk(EBinop(op, e1, e2), inf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function call(e, args, inf) {
|
||||||
|
return mk(ECall(e, args), inf);
|
||||||
|
}
|
||||||
|
|
||||||
|
function retNull(e:Expr,?pos) : Expr {
|
||||||
|
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 ) {
|
||||||
|
var names = [for( i in 0...args.length ) "_a"+uid++];
|
||||||
|
var rargs = [for( i in 0...args.length ) ident(names[i],ecall)];
|
||||||
|
if( !sync )
|
||||||
|
rargs.unshift(rest);
|
||||||
|
var rest = mk(sync ? ECall(rest,[call(ecall, rargs,ecall)]) : ECall(ecall, rargs), ecall);
|
||||||
|
var i = args.length - 1;
|
||||||
|
while( i >= 0 ) {
|
||||||
|
rest = toCps(args[i], fun(names[i], rest), exit);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
var syncFlag : Bool;
|
||||||
|
|
||||||
|
function isSync( e : Expr ) {
|
||||||
|
syncFlag = true;
|
||||||
|
checkSync(e);
|
||||||
|
return syncFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function isAsyncIdent( id : String ) {
|
||||||
|
return asyncIdents == null || asyncIdents.exists(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSync( e : Expr ) {
|
||||||
|
if( !syncFlag )
|
||||||
|
return;
|
||||||
|
switch( expr(e) ) {
|
||||||
|
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;
|
||||||
|
case EMeta("sync" | "async", _, _):
|
||||||
|
// isolated from the sync part
|
||||||
|
default:
|
||||||
|
Tools.iter(e, checkSync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveVars() {
|
||||||
|
return definedVars.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreVars(k) {
|
||||||
|
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 {
|
||||||
|
if( isSync(e) )
|
||||||
|
return call(rest, [buildSync(e, exit)],e);
|
||||||
|
switch( expr(e) ) {
|
||||||
|
case EBlock(el):
|
||||||
|
var el = el.copy();
|
||||||
|
var vold = saveVars();
|
||||||
|
lookupFunctions(el);
|
||||||
|
while( el.length > 0 ) {
|
||||||
|
var e = toCps(el.pop(), rest, exit);
|
||||||
|
rest = ignore(e);
|
||||||
|
}
|
||||||
|
restoreVars(vold);
|
||||||
|
return retNull(rest);
|
||||||
|
case EFunction(args, body, name, t):
|
||||||
|
var vold = saveVars();
|
||||||
|
if( name != null )
|
||||||
|
defineVar(name, Defined);
|
||||||
|
for( a in args )
|
||||||
|
defineVar(a.name, Defined);
|
||||||
|
args.unshift( { name : "_onEnd", t : null } );
|
||||||
|
var frest = ident("_onEnd",e);
|
||||||
|
var oldFun = currentFun;
|
||||||
|
currentFun = name;
|
||||||
|
var body = toCps(body, frest, frest);
|
||||||
|
var f = mk(EFunction(args, body, name, t),e);
|
||||||
|
restoreVars(vold);
|
||||||
|
return rest == null ? f : call(rest, [f],e);
|
||||||
|
case EParent(e):
|
||||||
|
return mk(EParent(toCps(e, rest, exit)),e);
|
||||||
|
case EMeta("sync", _, e):
|
||||||
|
return call(rest,[buildSync(e,exit)],e);
|
||||||
|
case EMeta("async", _, e):
|
||||||
|
var nothing = ignore();
|
||||||
|
return block([toCps(e,nothing,nothing),retNull(rest)],e);
|
||||||
|
case EMeta("split", _, e):
|
||||||
|
var args = switch( expr(e) ) { case EArrayDecl(el): el; default: throw "@split expression should be an array"; };
|
||||||
|
var args = [for( a in args ) fun("_rest", toCps(block([a],a), ident("_rest",a), exit))];
|
||||||
|
return call(ident("split",e), [rest, mk(EArrayDecl(args),e)],e);
|
||||||
|
case ECall(expr(_) => EIdent(i), args):
|
||||||
|
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):
|
||||||
|
return makeCall(field(e,"a_"+f,e), args, rest, exit);
|
||||||
|
case EFor(v, eit, eloop):
|
||||||
|
var id = ++uid;
|
||||||
|
var it = ident("_i" + id,e);
|
||||||
|
var oldLoop = currentLoop, oldBreak = currentBreak;
|
||||||
|
var loop = ident("_loop" + id,e);
|
||||||
|
currentLoop = loop;
|
||||||
|
currentBreak = function(inf) return block([retNull(rest, inf), mk(EReturn(),inf)], inf);
|
||||||
|
var efor = block([
|
||||||
|
mk(EVar("_i" + id, call(ident("makeIterator",eit),[eit],eit)),eit),
|
||||||
|
fun("_", block([
|
||||||
|
mk(EIf(mk(EUnop("!", true, call( field(it, "hasNext", it), [], it)),it), currentBreak(it)),it),
|
||||||
|
mk(EVar(v, call(field(it, "next",it), [], it)), it),
|
||||||
|
toCps(eloop, loop, exit),
|
||||||
|
], it),"_loop" + id),
|
||||||
|
retNull(loop, e),
|
||||||
|
], e);
|
||||||
|
currentLoop = oldLoop;
|
||||||
|
currentBreak = oldBreak;
|
||||||
|
return efor;
|
||||||
|
case EUnop(op = "!", prefix, eop):
|
||||||
|
return toCps(eop, fun("_r",call(rest, [mk(EUnop(op, prefix, ident("_r",e)),e)], e)), exit);
|
||||||
|
case EBinop(op, e1, e2):
|
||||||
|
switch( op ) {
|
||||||
|
case "=", "+=", "-=", "/=", "*=", "%=", "&=", "|=", "^=":
|
||||||
|
switch( expr(e1) ) {
|
||||||
|
case EIdent(_):
|
||||||
|
var id = "_r" + uid++;
|
||||||
|
return toCps(e2, fun(id, call(rest, [binop(op, e1, ident(id,e1),e1)], e1)), exit);
|
||||||
|
case EField(ef1, f):
|
||||||
|
var id1 = "_r" + uid++;
|
||||||
|
var id2 = "_r" + uid++;
|
||||||
|
return toCps(ef1, fun(id1, toCps(e2, fun(id2, call(rest, [binop(op, field(ident(id1, e1), f, ef1), ident(id2, e2), e)], e)), exit)), exit);
|
||||||
|
case EArray(earr, eindex):
|
||||||
|
var idArr = "_r" + uid++;
|
||||||
|
var idIndex = "_r" + uid++;
|
||||||
|
var idVal = "_r" + uid++;
|
||||||
|
return toCps(earr,fun(idArr, toCps(eindex, fun(idIndex, toCps(e2,
|
||||||
|
fun(idVal, call(rest, [binop(op, mk(EArray(ident(idArr,earr), ident(idIndex,eindex)),e1), ident(idVal,e1), e)], e))
|
||||||
|
, exit)), exit)),exit);
|
||||||
|
default:
|
||||||
|
throw "assert " + e1;
|
||||||
|
}
|
||||||
|
case "||":
|
||||||
|
var id1 = "_r" + uid++;
|
||||||
|
var id2 = "_r" + uid++;
|
||||||
|
return toCps(e1, fun(id1, mk(EIf(binop("==", ident(id1,e1), ident("true",e1), e1),call(rest,[ident("true",e1)],e1),toCps(e2, rest, exit)),e)), exit);
|
||||||
|
case "&&":
|
||||||
|
var id1 = "_r" + uid++;
|
||||||
|
var id2 = "_r" + uid++;
|
||||||
|
return toCps(e1, fun(id1, mk(EIf(binop("!=", ident(id1,e1), ident("true",e1), e1),call(rest,[ident("false",e1)],e1),toCps(e2, rest, exit)),e)), exit);
|
||||||
|
default:
|
||||||
|
var id1 = "_r" + uid++;
|
||||||
|
var id2 = "_r" + uid++;
|
||||||
|
return toCps(e1, fun(id1, toCps(e2, fun(id2, call(rest, [binop(op, ident(id1,e1), ident(id2,e2), e)], e)), exit)), exit);
|
||||||
|
}
|
||||||
|
case EIf(cond, e1, e2), ETernary(cond, e1, e2):
|
||||||
|
return toCps(cond, fun("_c", mk(EIf(ident("_c",cond), toCps(e1, rest, exit), e2 == null ? retNull(rest) : toCps(e2, rest, exit)),e)), exit);
|
||||||
|
case EWhile(cond, ewh):
|
||||||
|
var id = ++uid;
|
||||||
|
var loop = ident("_loop" + id, cond);
|
||||||
|
var oldLoop = currentLoop, oldBreak = currentBreak;
|
||||||
|
currentLoop = loop;
|
||||||
|
currentBreak = function(e) return block([retNull(rest,e), mk(EReturn(),e)],e);
|
||||||
|
var ewhile = block([
|
||||||
|
fun("_r",
|
||||||
|
toCps(cond, fun("_c", mk(EIf(ident("_c", cond), toCps(ewh, loop, exit), retNull(rest,cond)),cond)), exit)
|
||||||
|
, "_loop"+id),
|
||||||
|
retNull(loop, cond),
|
||||||
|
],e);
|
||||||
|
currentLoop = oldLoop;
|
||||||
|
currentBreak = oldBreak;
|
||||||
|
return ewhile;
|
||||||
|
case EReturn(eret):
|
||||||
|
return eret == null ? retNull(exit, e) : toCps(eret, exit, exit);
|
||||||
|
case EObject(fields):
|
||||||
|
var id = "_o" + uid++;
|
||||||
|
var rest = call(rest, [ident(id,e)], e);
|
||||||
|
fields.reverse();
|
||||||
|
for( f in fields )
|
||||||
|
rest = toCps(f.e, fun("_r", block([
|
||||||
|
binop("=", mk(EField(ident(id,f.e), f.name),f.e), ident("_r",f.e), f.e),
|
||||||
|
rest,
|
||||||
|
],f.e)),exit);
|
||||||
|
return block([
|
||||||
|
mk(EVar(id, mk(EObject([]),e)),e),
|
||||||
|
rest,
|
||||||
|
],e);
|
||||||
|
case EArrayDecl(el):
|
||||||
|
var id = "_a" + uid++;
|
||||||
|
var rest = call(rest, [ident(id,e)], e);
|
||||||
|
var i = el.length - 1;
|
||||||
|
while( i >= 0 ) {
|
||||||
|
var e = el[i];
|
||||||
|
rest = toCps(e, fun("_r", block([
|
||||||
|
binop("=", mk(EArray(ident(id,e), mk(EConst(CInt(i)),e)),e), ident("_r",e), e),
|
||||||
|
rest,
|
||||||
|
],e)), exit);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return block([
|
||||||
|
mk(EVar(id, mk(EArrayDecl([]),e)),e),
|
||||||
|
rest,
|
||||||
|
],e);
|
||||||
|
case EArray(earr, eindex):
|
||||||
|
var id1 = "_r" + uid++;
|
||||||
|
var id2 = "_r" + uid++;
|
||||||
|
return toCps(earr, fun(id1, toCps(eindex, fun(id2, call(rest, [mk(EArray(ident(id1,e), ident(id2,e)),e)], e)), exit)), exit);
|
||||||
|
case EVar(v, t, ev):
|
||||||
|
if( ev == null )
|
||||||
|
return block([e, retNull(rest, e)], e);
|
||||||
|
return block([
|
||||||
|
mk(EVar(v, t),e),
|
||||||
|
toCps(ev, fun("_r", block([binop("=", ident(v,e), ident("_r",e), e), retNull(rest,e)], e)), exit),
|
||||||
|
],e);
|
||||||
|
case EConst(_), EIdent(_), EUnop(_), EField(_):
|
||||||
|
return call(rest, [e], e);
|
||||||
|
case ENew(cl, args):
|
||||||
|
var names = [for( i in 0...args.length ) "_a"+uid++];
|
||||||
|
var rargs = [for( i in 0...args.length ) ident(names[i], args[i])];
|
||||||
|
var rest = call(rest,[mk(ENew(cl, rargs),e)],e);
|
||||||
|
var i = args.length - 1;
|
||||||
|
while( i >= 0 ) {
|
||||||
|
rest = toCps(args[i], fun(names[i], rest), exit);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return rest;
|
||||||
|
case EBreak:
|
||||||
|
if( currentBreak == null ) throw "Break outside loop";
|
||||||
|
return currentBreak(e);
|
||||||
|
case EContinue:
|
||||||
|
if( currentLoop == null ) throw "Continue outside loop";
|
||||||
|
return block([retNull(currentLoop, e), mk(EReturn(),e)], e);
|
||||||
|
case ESwitch(v, cases, def):
|
||||||
|
var cases = [for( c in cases ) { values : c.values, expr : toCps(c.expr, rest, exit) } ];
|
||||||
|
return toCps(v, mk(EFunction([ { name : "_c", t : null } ], mk(ESwitch(ident("_c",v), cases, def == null ? retNull(rest) : toCps(def, rest, exit)),e)),e), exit );
|
||||||
|
case EThrow(v):
|
||||||
|
return toCps(v, mk(EFunction([ { name : "_v", t : null } ], mk(EThrow(v),v)), v), exit);
|
||||||
|
case EMeta(name,_,e) if( name.charCodeAt(0) == ":".code ): // ignore custom ":" metadata
|
||||||
|
return toCps(e, rest, exit);
|
||||||
|
//case EDoWhile(_), ETry(_), ECall(_):
|
||||||
|
default:
|
||||||
|
throw "Unsupported async expression " + Printer.toString(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncInterp extends Interp {
|
||||||
|
|
||||||
|
public function setContext( api : Dynamic ) {
|
||||||
|
|
||||||
|
var funs = new Array();
|
||||||
|
for( v in variables.keys() )
|
||||||
|
if( Reflect.isFunction(variables.get(v)) )
|
||||||
|
funs.push({ v : v, obj : null });
|
||||||
|
|
||||||
|
variables.set("split", split);
|
||||||
|
variables.set("makeIterator", makeIterator);
|
||||||
|
|
||||||
|
var c = Type.getClass(api);
|
||||||
|
for( f in (c == null ? Reflect.fields(api) : Type.getInstanceFields(c)) ) {
|
||||||
|
var fv = Reflect.field(api, f);
|
||||||
|
if( !Reflect.isFunction(fv) ) continue;
|
||||||
|
if( f.charCodeAt(0) == "_".code ) f = f.substr(1);
|
||||||
|
variables.set(f, fv);
|
||||||
|
// create the async wrapper if doesn't exists
|
||||||
|
if( f.substr(0, 2) != "a_" )
|
||||||
|
funs.push({ v : f, obj : api });
|
||||||
|
}
|
||||||
|
|
||||||
|
for( v in funs ) {
|
||||||
|
if( variables.exists("a_" + v.v) ) continue;
|
||||||
|
var fv : Dynamic = variables.get(v.v);
|
||||||
|
var obj = v.obj;
|
||||||
|
variables.set("a_" + v.v, Reflect.makeVarArgs(function(args:Array<Dynamic>) {
|
||||||
|
var onEnd = args.shift();
|
||||||
|
onEnd(Reflect.callMethod(obj, fv, args));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasMethod( name : String ) {
|
||||||
|
var v = variables.get(name);
|
||||||
|
return v != null && Reflect.isFunction(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function callValue( value : Dynamic, args : Array<Dynamic>, ?onResult : Dynamic -> Void, ?vthis : {} ) {
|
||||||
|
var oldThis = variables.get("this");
|
||||||
|
if( vthis != null )
|
||||||
|
variables.set("this", vthis);
|
||||||
|
if( onResult == null )
|
||||||
|
onResult = function(_) {};
|
||||||
|
args.unshift(onResult);
|
||||||
|
Reflect.callMethod(null, value, args);
|
||||||
|
variables.set("this", oldThis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function callAsync( id : String, args, ?onResult, ?vthis : {} ) {
|
||||||
|
var v = variables.get(id);
|
||||||
|
if( v == null )
|
||||||
|
throw "Missing function " + id + "()";
|
||||||
|
callValue(v, args, onResult, vthis);
|
||||||
|
}
|
||||||
|
|
||||||
|
function split( rest : Dynamic -> Void, args : Array<Dynamic> ) {
|
||||||
|
if( args.length == 0 )
|
||||||
|
rest(null);
|
||||||
|
else {
|
||||||
|
var count = args.length;
|
||||||
|
function next(_) {
|
||||||
|
if( --count == 0 ) rest(null);
|
||||||
|
}
|
||||||
|
for( a in args )
|
||||||
|
a(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override function fcall( o : Dynamic, f : String, args : Array<Dynamic> ) : Dynamic {
|
||||||
|
var m = Reflect.field(o, f);
|
||||||
|
if( m == null ) {
|
||||||
|
if( f.substr(0, 2) == "a_" ) {
|
||||||
|
m = Reflect.field(o, f.substr(2));
|
||||||
|
// fallback on sync version
|
||||||
|
if( m != null ) {
|
||||||
|
var onEnd = args.shift();
|
||||||
|
onEnd(call(o, m, args));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// fallback on generic script
|
||||||
|
m = Reflect.field(o, "scriptCall");
|
||||||
|
if( m != null ) {
|
||||||
|
call(o, m, [args.shift(), f.substr(2), args]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// fallback on generic script
|
||||||
|
m = Reflect.field(o, "scriptCall");
|
||||||
|
if( m != null ) {
|
||||||
|
var result : Dynamic = null;
|
||||||
|
call(o, m, [function(r) result = r, f, args]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error(ECustom(o + " has no method " + f));
|
||||||
|
}
|
||||||
|
return call(o, m, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+41
-25
@@ -1,26 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, Nicolas Cannasse
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
*
|
||||||
* - Redistributions of source code must retain the above copyright
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
* to deal in the Software without restriction, including without limitation
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
* documentation and/or other materials provided with the distribution.
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* all copies or substantial portions of the Software.
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
*
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
* DEALINGS IN THE SOFTWARE.
|
||||||
* DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
import hscript.Expr;
|
import hscript.Expr;
|
||||||
@@ -75,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 ) {
|
||||||
@@ -110,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;
|
||||||
}
|
}
|
||||||
@@ -146,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):
|
||||||
@@ -247,11 +245,22 @@ class Bytes {
|
|||||||
}
|
}
|
||||||
bout.addByte(255);
|
bout.addByte(255);
|
||||||
if( def == null ) bout.addByte(255) else doEncode(def);
|
if( def == null ) bout.addByte(255) else doEncode(def);
|
||||||
|
case EMeta(name,args,e):
|
||||||
|
doEncodeString(name);
|
||||||
|
bout.addByte(args == null ? 0 : args.length + 1);
|
||||||
|
if( args != null ) for( e in args ) doEncode(e);
|
||||||
|
doEncode(e);
|
||||||
|
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 };
|
||||||
@@ -366,6 +375,13 @@ class Bytes {
|
|||||||
case 24:
|
case 24:
|
||||||
var cond = doDecode();
|
var cond = doDecode();
|
||||||
EDoWhile(cond,doDecode());
|
EDoWhile(cond,doDecode());
|
||||||
|
case 25:
|
||||||
|
var name = doDecodeString();
|
||||||
|
var count = bin.get(pin++);
|
||||||
|
var args = count == 0 ? null : [for( i in 0...count - 1 ) doDecode()];
|
||||||
|
EMeta(name, args, doDecode());
|
||||||
|
case 26:
|
||||||
|
ECheckType(doDecode(), CTPath(["Void"]));
|
||||||
case 255:
|
case 255:
|
||||||
null;
|
null;
|
||||||
default:
|
default:
|
||||||
|
|||||||
+1242
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
|||||||
|
package hscript;
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
// Runs support for custom classes in these
|
||||||
|
public static final ALLOWED_CUSTOM_CLASSES = [
|
||||||
|
"flixel",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Runs support for abstract support in these
|
||||||
|
public static final ALLOWED_ABSTRACT_AND_ENUM = [
|
||||||
|
"flixel",
|
||||||
|
"openfl.display.BlendMode",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Incase any of your files fail
|
||||||
|
// These are the module names
|
||||||
|
public static final DISALLOW_CUSTOM_CLASSES = [
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
public static final DISALLOW_ABSTRACT_AND_ENUM = [
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
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');
|
||||||
|
if(cl == null)
|
||||||
|
ogInterp.error(EInvalidClass(extend));
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (key => value in capturedLocals) {
|
||||||
|
if(!disallowCopy.contains(key)) {
|
||||||
|
interp.locals.set(key, {r: value, depth: -1});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (key => value in ogInterp.variables) {
|
||||||
|
if(!disallowCopy.contains(key)) {
|
||||||
|
interp.variables.set(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() {}
|
||||||
|
}
|
||||||
+100
-60
@@ -1,26 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, Nicolas Cannasse
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
*
|
||||||
* - Redistributions of source code must retain the above copyright
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
* to deal in the Software without restriction, including without limitation
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
* documentation and/or other materials provided with the distribution.
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* all copies or substantial portions of the Software.
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
*
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
* DEALINGS IN THE SOFTWARE.
|
||||||
* DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
|
|
||||||
@@ -43,42 +40,52 @@ 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> );
|
||||||
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
EIf( cond : Expr, e1 : Expr, ?e2 : Expr );
|
||||||
EWhile( cond : Expr, e : Expr );
|
EWhile( cond : Expr, e : Expr );
|
||||||
EFor( v : String, it : Expr, e : Expr );
|
EFor( v : String, it : Expr, e : Expr, ?ithv: String);
|
||||||
EBreak;
|
EBreak;
|
||||||
EContinue;
|
EContinue;
|
||||||
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType );
|
EFunction( args : Array<Argument>, e : Expr, ?name : String, ?ret : CType, ?isPublic : Bool, ?isStatic : Bool, ?isOverride : Bool );
|
||||||
EReturn( ?e : Expr );
|
EReturn( ?e : Expr );
|
||||||
EArray( e : Expr, index : Expr );
|
EArray( e : Expr, index : Expr );
|
||||||
EArrayDecl( e : Array<Expr> );
|
EArrayDecl( e : Array<Expr>, ?wantedType: CType );
|
||||||
ENew( cl : String, params : Array<Expr> );
|
ENew( cl : String, params : Array<Expr> );
|
||||||
EThrow( e : Expr );
|
EThrow( e : Expr );
|
||||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||||
EObject( fl : Array<{ name : String, e : Expr }> );
|
EObject( fl : Array<{ name : String, e : Expr }> );
|
||||||
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
|
||||||
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr);
|
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr );
|
||||||
EDoWhile( cond : Expr, e : Expr);
|
EDoWhile( cond : Expr, e : Expr);
|
||||||
|
EMeta( name : String, args : Array<Expr>, e : Expr );
|
||||||
|
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 };
|
typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr };
|
||||||
|
|
||||||
|
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
|
||||||
|
|
||||||
enum CType {
|
enum CType {
|
||||||
CTPath( path : Array<String>, ?params : Array<CType> );
|
CTPath( path : Array<String>, ?params : Array<CType> );
|
||||||
CTFun( args : Array<CType>, ret : CType );
|
CTFun( args : Array<CType>, ret : CType );
|
||||||
CTAnon( fields : Array<{ name : String, t : CType }> );
|
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
|
||||||
CTParent( t : CType );
|
CTParent( t : CType );
|
||||||
|
CTOpt( t : CType );
|
||||||
|
CTNamed( n : String, t : CType );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if hscriptPos
|
#if hscriptPos
|
||||||
@@ -95,39 +102,8 @@ class Error {
|
|||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
this.line = line;
|
this.line = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function errorDefToString(): String {
|
|
||||||
switch (e) {
|
|
||||||
case EInvalidChar(c):
|
|
||||||
return "Invalid character: '"+c+"'";
|
|
||||||
|
|
||||||
case EUnexpected(s):
|
|
||||||
return "Unexpected token: \""+s+"\"";
|
|
||||||
|
|
||||||
case EUnterminatedString:
|
|
||||||
return "Unterminated string";
|
|
||||||
|
|
||||||
case EUnterminatedComment:
|
|
||||||
return "Unterminated comment";
|
|
||||||
|
|
||||||
case EUnknownVariable(v):
|
|
||||||
return "Unknown variable: "+v;
|
|
||||||
|
|
||||||
case EInvalidIterator(v):
|
|
||||||
return "Invalid iterator: "+v;
|
|
||||||
|
|
||||||
case EInvalidOp(op):
|
|
||||||
return "Invalid operator: "+op;
|
|
||||||
|
|
||||||
case EInvalidAccess(f):
|
|
||||||
return "Invalid access to field "+f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toString(): String {
|
public function toString(): String {
|
||||||
var message = errorDefToString();
|
return Printer.errorToString(this);
|
||||||
message = origin + ":" + line + ": " + message;
|
|
||||||
return message;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enum ErrorDef {
|
enum ErrorDef {
|
||||||
@@ -138,8 +114,72 @@ enum Error {
|
|||||||
EUnexpected( s : String );
|
EUnexpected( s : String );
|
||||||
EUnterminatedString;
|
EUnterminatedString;
|
||||||
EUnterminatedComment;
|
EUnterminatedComment;
|
||||||
|
EInvalidPreprocessor( msg : String );
|
||||||
EUnknownVariable( v : String );
|
EUnknownVariable( v : String );
|
||||||
EInvalidIterator( v : String );
|
EInvalidIterator( v : String );
|
||||||
EInvalidOp( op : String );
|
EInvalidOp( op : String );
|
||||||
EInvalidAccess( f : String );
|
EInvalidAccess( f : String );
|
||||||
|
ECustom( msg : String );
|
||||||
|
EInvalidClass( className : String);
|
||||||
|
EAlreadyExistingClass( className : String);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum ModuleDecl {
|
||||||
|
DPackage( path : Array<String> );
|
||||||
|
DImport( path : Array<String>, ?everything : Bool );
|
||||||
|
DClass( c : ClassDecl );
|
||||||
|
DTypedef( c : TypeDecl );
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ModuleType = {
|
||||||
|
var name : String;
|
||||||
|
var params : {}; // TODO : not yet parsed
|
||||||
|
var meta : Metadata;
|
||||||
|
var isPrivate : Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ClassDecl = {> ModuleType,
|
||||||
|
var extend : Null<CType>;
|
||||||
|
var implement : Array<CType>;
|
||||||
|
var fields : Array<FieldDecl>;
|
||||||
|
var isExtern : Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TypeDecl = {> ModuleType,
|
||||||
|
var t : CType;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef FieldDecl = {
|
||||||
|
var name : String;
|
||||||
|
var meta : Metadata;
|
||||||
|
var kind : FieldKind;
|
||||||
|
var access : Array<FieldAccess>;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FieldAccess {
|
||||||
|
APublic;
|
||||||
|
APrivate;
|
||||||
|
AInline;
|
||||||
|
AOverride;
|
||||||
|
AStatic;
|
||||||
|
AMacro;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FieldKind {
|
||||||
|
KFunction( f : FunctionDecl );
|
||||||
|
KVar( v : VarDecl );
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef FunctionDecl = {
|
||||||
|
var args : Array<Argument>;
|
||||||
|
var expr : Expr;
|
||||||
|
var ret : Null<CType>;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef VarDecl = {
|
||||||
|
var get : Null<String>;
|
||||||
|
var set : Null<String>;
|
||||||
|
var expr : Null<Expr>;
|
||||||
|
var type : Null<CType>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
+896
-489
File diff suppressed because it is too large
Load Diff
+53
-30
@@ -1,26 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, Nicolas Cannasse
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
*
|
||||||
* - Redistributions of source code must retain the above copyright
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
* to deal in the Software without restriction, including without limitation
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
* documentation and/or other materials provided with the distribution.
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
* all copies or substantial portions of the Software.
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
*
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
* DEALINGS IN THE SOFTWARE.
|
||||||
* DAMAGE.
|
|
||||||
*/
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
import hscript.Expr.Error;
|
import hscript.Expr.Error;
|
||||||
@@ -79,6 +76,11 @@ class Macro {
|
|||||||
#if haxe3
|
#if haxe3
|
||||||
case OpArrow: "=>";
|
case OpArrow: "=>";
|
||||||
#end
|
#end
|
||||||
|
#if (haxe_ver >= 4)
|
||||||
|
case OpIn: "in";
|
||||||
|
#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,10 +133,18 @@ 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 ) {
|
||||||
tf.push( { name : f.name, meta : [], doc : null, access : [], kind : FVar(convertType(f.t),null), pos : p } );
|
var meta = f.meta == null ? [] : [for( m in f.meta ) { name : m.name, params : m.params == null ? [] : [for( e in m.params ) convert(e)], pos : p }];
|
||||||
|
tf.push( { name : f.name, meta : meta, doc : null, access : [], kind : FVar(convertType(f.t), null), pos : p } );
|
||||||
|
}
|
||||||
TAnonymous(tf);
|
TAnonymous(tf);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -182,14 +196,16 @@ class Macro {
|
|||||||
EWhile(convert(c), convert(e), true);
|
EWhile(convert(c), convert(e), true);
|
||||||
case EDoWhile(c, e):
|
case EDoWhile(c, e):
|
||||||
EWhile(convert(c), convert(e), false);
|
EWhile(convert(c), convert(e), false);
|
||||||
#if (haxe_211 || haxe3)
|
|
||||||
case EFor(v, it, efor):
|
case EFor(v, it, efor):
|
||||||
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
#if (haxe_ver >= 4)
|
||||||
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
|
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||||
#else
|
EFor({ expr : EBinop(OpIn,{ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
|
||||||
case EFor(v, it, e):
|
#elseif (haxe_211 || haxe3)
|
||||||
EFor(v, convert(it), convert(e));
|
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||||
#end
|
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
|
||||||
|
#else
|
||||||
|
EFor(v, convert(it), convert(efor));
|
||||||
|
#end
|
||||||
case EBreak:
|
case EBreak:
|
||||||
EBreak;
|
EBreak;
|
||||||
case EContinue:
|
case EContinue:
|
||||||
@@ -203,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),
|
||||||
@@ -231,6 +247,13 @@ class Macro {
|
|||||||
ETernary(convert(cond), convert(e1), convert(e2));
|
ETernary(convert(cond), convert(e1), convert(e2));
|
||||||
case ESwitch(e, cases, edef):
|
case ESwitch(e, cases, edef):
|
||||||
ESwitch(convert(e), [for( c in cases ) { values : [for( v in c.values ) convert(v)], expr : convert(c.expr) } ], edef == null ? null : convert(edef));
|
ESwitch(convert(e), [for( c in cases ) { values : [for( v in c.values ) convert(v)], expr : convert(c.expr) } ], edef == null ? null : convert(edef));
|
||||||
|
case EMeta(m, params, esub):
|
||||||
|
var mpos = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
|
||||||
|
EMeta({ name : m, params : params == null ? [] : [for( p in params ) convert(p)], pos : mpos }, convert(esub));
|
||||||
|
case ECheckType(e, t):
|
||||||
|
ECheckType(convert(e), convertType(t));
|
||||||
|
default:
|
||||||
|
null;
|
||||||
}, 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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1360
-452
File diff suppressed because it is too large
Load Diff
+117
-8
@@ -1,3 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
import hscript.Expr;
|
import hscript.Expr;
|
||||||
|
|
||||||
@@ -16,10 +37,20 @@ class Printer {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function typeToString( t : CType ) {
|
||||||
|
buf = new StringBuf();
|
||||||
|
tabs = "";
|
||||||
|
type(t);
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
inline function add<T>(s:T) buf.add(s);
|
inline function add<T>(s:T) buf.add(s);
|
||||||
|
|
||||||
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 ) {
|
||||||
@@ -31,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 -> ");
|
||||||
@@ -70,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);
|
||||||
@@ -78,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 ) {
|
||||||
@@ -101,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 + " ");
|
||||||
@@ -154,8 +217,11 @@ class Printer {
|
|||||||
add(" while ( ");
|
add(" while ( ");
|
||||||
expr(cond);
|
expr(cond);
|
||||||
add(" )");
|
add(" )");
|
||||||
case EFor(v, it, e):
|
case EFor(v, it, e, ithv):
|
||||||
add("for( "+v+" in ");
|
if(ithv != null)
|
||||||
|
add("for( "+ithv+" => "+v+" in ");
|
||||||
|
else
|
||||||
|
add("for( "+v+" in ");
|
||||||
expr(it);
|
expr(it);
|
||||||
add(" ) ");
|
add(" ) ");
|
||||||
expr(e);
|
expr(e);
|
||||||
@@ -163,7 +229,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);
|
||||||
@@ -190,7 +256,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 ) {
|
||||||
@@ -258,6 +324,26 @@ class Printer {
|
|||||||
add(";\n");
|
add(";\n");
|
||||||
}
|
}
|
||||||
add("}");
|
add("}");
|
||||||
|
case EMeta(name, args, e):
|
||||||
|
add("@");
|
||||||
|
add(name);
|
||||||
|
if( args != null && args.length > 0 ) {
|
||||||
|
add("(");
|
||||||
|
var first = true;
|
||||||
|
for( a in args ) {
|
||||||
|
if( first ) first = false else add(", ");
|
||||||
|
expr(e);
|
||||||
|
}
|
||||||
|
add(")");
|
||||||
|
}
|
||||||
|
add(" ");
|
||||||
|
expr(e);
|
||||||
|
case ECheckType(e, t):
|
||||||
|
add("(");
|
||||||
|
expr(e);
|
||||||
|
add(" : ");
|
||||||
|
addType(t);
|
||||||
|
add(")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,4 +351,27 @@ class Printer {
|
|||||||
return new Printer().exprToString(e);
|
return new Printer().exprToString(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public static function errorToString( e : Expr.Error ) {
|
||||||
|
var message = switch( #if hscriptPos e.e #else e #end ) {
|
||||||
|
case EInvalidChar(c): "Invalid character: '"+(StringTools.isEof(c) ? "EOF (End Of File)" : String.fromCharCode(c))+"' ("+c+")";
|
||||||
|
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
||||||
|
case EUnterminatedString: "Unterminated string";
|
||||||
|
case EUnterminatedComment: "Unterminated comment";
|
||||||
|
case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")";
|
||||||
|
case EUnknownVariable(v): "Unknown variable: "+v;
|
||||||
|
case EInvalidIterator(v): "Invalid iterator: "+v;
|
||||||
|
case EInvalidOp(op): "Invalid operator: "+op;
|
||||||
|
case EInvalidAccess(f): "Invalid access to field " + f;
|
||||||
|
case ECustom(msg): msg;
|
||||||
|
case EInvalidClass(cla): "Invalid class: " + cla + " was not found.";
|
||||||
|
case EAlreadyExistingClass(cla): 'Custom Class named $cla already exists.';
|
||||||
|
};
|
||||||
|
#if hscriptPos
|
||||||
|
return e.origin + ":" + e.line + ": " + message;
|
||||||
|
#else
|
||||||
|
return message;
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+50
-4
@@ -1,11 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C)2008-2017 Haxe Foundation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
package hscript;
|
package hscript;
|
||||||
import hscript.Expr;
|
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( e ) {
|
switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_):
|
case EConst(_), EIdent(_):
|
||||||
|
case EImport(c): f(e);
|
||||||
|
case EClass(_, e, _, _): for( a in e ) f(a);
|
||||||
case EVar(_, _, e): if( e != null ) f(e);
|
case EVar(_, _, e): if( e != null ) f(e);
|
||||||
case EParent(e): f(e);
|
case EParent(e): f(e);
|
||||||
case EBlock(el): for( e in el ) f(e);
|
case EBlock(el): for( e in el ) f(e);
|
||||||
@@ -34,12 +57,15 @@ class Tools {
|
|||||||
f(c.expr);
|
f(c.expr);
|
||||||
}
|
}
|
||||||
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 ECheckType(e,_): f(e);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function map( e : Expr, f : Expr -> Expr ) {
|
public static function map( e : Expr, f : Expr -> Expr ) {
|
||||||
return switch( e ) {
|
var edef = switch( expr(e) ) {
|
||||||
case EConst(_), EIdent(_): e;
|
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
|
||||||
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)]);
|
||||||
@@ -51,7 +77,6 @@ class Tools {
|
|||||||
case EWhile(c, e): EWhile(f(c),f(e));
|
case EWhile(c, e): EWhile(f(c),f(e));
|
||||||
case EDoWhile(c, e): EDoWhile(f(c),f(e));
|
case EDoWhile(c, e): EDoWhile(f(c),f(e));
|
||||||
case EFor(v, it, e): EFor(v, f(it), f(e));
|
case EFor(v, it, e): EFor(v, f(it), f(e));
|
||||||
case EBreak, EContinue: e;
|
|
||||||
case EFunction(args, e, name, t): EFunction(args, f(e), name, t);
|
case EFunction(args, e, name, t): EFunction(args, f(e), name, t);
|
||||||
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
case EReturn(e): EReturn(if( e != null ) f(e) else null);
|
||||||
case EArray(e, i): EArray(f(e),f(i));
|
case EArray(e, i): EArray(f(e),f(i));
|
||||||
@@ -62,7 +87,28 @@ class Tools {
|
|||||||
case EObject(fl): EObject([for( fi in fl ) { name : fi.name, e : f(fi.e) }]);
|
case EObject(fl): EObject([for( fi in fl ) { name : fi.name, e : f(fi.e) }]);
|
||||||
case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2));
|
case 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 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
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,437 @@
|
|||||||
|
package hscript.macros;
|
||||||
|
|
||||||
|
#if macro
|
||||||
|
import haxe.macro.Type.ClassType;
|
||||||
|
import Type.ValueType;
|
||||||
|
import haxe.macro.Expr.Function;
|
||||||
|
import haxe.macro.Expr;
|
||||||
|
import haxe.macro.Type.MetaAccess;
|
||||||
|
import haxe.macro.Type.FieldKind;
|
||||||
|
import haxe.macro.Type.ClassField;
|
||||||
|
import haxe.macro.Type.VarAccess;
|
||||||
|
import haxe.macro.*;
|
||||||
|
import Sys;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class ClassExtendMacro {
|
||||||
|
public static inline final FUNC_PREFIX = "_HX_SUPER__";
|
||||||
|
public static inline final CLASS_SUFFIX = "_HSX";
|
||||||
|
|
||||||
|
public static var unallowedMetas:Array<String> = [":bitmap", ":noCustomClass", ":generic"];
|
||||||
|
|
||||||
|
public static var modifiedClasses:Array<String> = [];
|
||||||
|
|
||||||
|
public static function init() {
|
||||||
|
#if !display
|
||||||
|
#if CUSTOM_CLASSES
|
||||||
|
if(Context.defined("display")) return;
|
||||||
|
for(apply in Config.ALLOWED_CUSTOM_CLASSES) {
|
||||||
|
Compiler.addGlobalMetadata(apply, "@:build(hscript.macros.ClassExtendMacro.build())");
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
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.isAbstract || cl.isExtern || cl.isFinal || cl.isInterface) return fields;
|
||||||
|
if (!cl.name.endsWith("_Impl_") && !cl.name.endsWith(CLASS_SUFFIX) && !cl.name.endsWith("_HSC")) {
|
||||||
|
var metas = cl.meta.get();
|
||||||
|
|
||||||
|
for(m in metas)
|
||||||
|
if (unallowedMetas.contains(m.name))
|
||||||
|
return fields;
|
||||||
|
|
||||||
|
if(cl.params.length > 0)
|
||||||
|
return fields;
|
||||||
|
|
||||||
|
var key = cl.module;
|
||||||
|
var fkey = cl.module + "." + cl.name;
|
||||||
|
if(key == "sys.thread.FixedThreadPool") return fields; // Error: Type name sys.thread.Worker_HSX is redefined from module sys.thread.FixedThreadPool
|
||||||
|
if(key == "StdTypes") return fields; // Error: Cant extend basic class
|
||||||
|
if(key == "Xml") return fields; // Error: Cant extend basic class
|
||||||
|
if(key == "Date") return fields; // Error: Cant extend basic class
|
||||||
|
if(key == "away3d.tools.commands.Mirror") return fields; // Error: Unknown identifier
|
||||||
|
if(key == "away3d.tools.commands.SphereMaker") return fields; // Error: Unknown identifier
|
||||||
|
if(key == "away3d.tools.commands.Weld") return fields; // Error: Unknown identifier
|
||||||
|
if(fkey == "hscript.CustomClassHandler.TemplateClass") return fields; // Error: Redefined
|
||||||
|
if(key == "sys.thread.EventLoop") return fields; // Error: cant override force inlined
|
||||||
|
if(Config.DISALLOW_CUSTOM_CLASSES.contains(cl.module) || Config.DISALLOW_CUSTOM_CLASSES.contains(fkey)) return fields;
|
||||||
|
if(cl.module.contains("_")) return fields; // Weird issue, sorry
|
||||||
|
|
||||||
|
var superFields = [];
|
||||||
|
if(cl.superClass != null) {
|
||||||
|
var _superFields = cl.superClass.t.get().fields.get();
|
||||||
|
_superFields = []; // Comment to enable super support, (broken)
|
||||||
|
for(field in _superFields) {
|
||||||
|
if(!field.kind.match(FMethod(_))) // only catch methods
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var nfield = @:privateAccess TypeTools.toField(field);
|
||||||
|
switch ([field.kind, field.type]) {
|
||||||
|
case [FMethod(kind), TFun(args, ret)]:
|
||||||
|
if(kind == MethInline)
|
||||||
|
nfield.access.push(AInline);
|
||||||
|
if(kind == MethDynamic)
|
||||||
|
nfield.access.push(ADynamic);
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(nfield.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (fun.params != null && fun.params.length > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fun.ret = Utils.fixStdTypes(fun.ret);
|
||||||
|
|
||||||
|
var metas = nfield.meta;
|
||||||
|
var defaultValues:Map<String, Dynamic> = [];
|
||||||
|
var defaultEntry = null;
|
||||||
|
var isGeneric = false;
|
||||||
|
for(m in metas) {
|
||||||
|
if(m.name == ":value") {
|
||||||
|
defaultEntry = m;
|
||||||
|
switch(m.params[0].expr) {
|
||||||
|
case EObjectDecl(fields):
|
||||||
|
for(fil in fields)
|
||||||
|
defaultValues[fil.field] = fil.expr;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m.name == ":generic")
|
||||||
|
isGeneric = true;
|
||||||
|
}
|
||||||
|
if(isGeneric) continue;
|
||||||
|
|
||||||
|
if(defaultEntry != null)
|
||||||
|
metas.remove(defaultEntry);
|
||||||
|
|
||||||
|
for(arg in fun.args) {
|
||||||
|
var opt = false;
|
||||||
|
if(defaultValues.exists(arg.name)) {
|
||||||
|
arg.value = defaultValues[arg.name];
|
||||||
|
arg.opt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg.type = Utils.fixStdTypes(arg.type);
|
||||||
|
|
||||||
|
if(arg.opt) {
|
||||||
|
if(arg.type.getParameters()[0].name != "Null")
|
||||||
|
arg.type = TPath({name: "Null", params: [TPType(arg.type)], pack: []});//macro {Null<Dynamic>};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
superFields.push(nfield);
|
||||||
|
} catch(e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//superFields = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var shadowClass = macro class {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var definedFields:Array<String> = [];
|
||||||
|
|
||||||
|
//trace(getModuleName(cl));
|
||||||
|
|
||||||
|
var hasNew = false;
|
||||||
|
|
||||||
|
for(_field in [fields.copy(), superFields.copy()])
|
||||||
|
for(f in _field) {
|
||||||
|
if (f == null)
|
||||||
|
continue;
|
||||||
|
if (f.name == "new") {
|
||||||
|
hasNew = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (f.name.startsWith(FUNC_PREFIX))
|
||||||
|
continue;
|
||||||
|
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern) || f.access.contains(AInline))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(f.name == "hget" || f.name == "hset") continue; // sorry, no overwriting the hget and hset in custom classes, yet
|
||||||
|
if(definedFields.contains(f.name)) continue; // no duplicate fields
|
||||||
|
|
||||||
|
for(m in f.meta)
|
||||||
|
if (unallowedMetas.contains(m.name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(f.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (fun == null)
|
||||||
|
continue;
|
||||||
|
if (fun.params != null && fun.params.length > 0) // TODO: Support for this maybe?
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(fun.params == null)
|
||||||
|
fun.params = [];
|
||||||
|
|
||||||
|
var overrideExpr:Expr;
|
||||||
|
var returns:Bool = !fun.ret.match(TPath({name: "Void"}));
|
||||||
|
|
||||||
|
var name = f.name;
|
||||||
|
|
||||||
|
var arguments = fun.args == null ? [] : [for(a in fun.args) macro $i{a.name}];
|
||||||
|
|
||||||
|
if (returns) {
|
||||||
|
overrideExpr = macro {
|
||||||
|
var name:String = $v{name};
|
||||||
|
|
||||||
|
if (__interp != null) {
|
||||||
|
var v:Dynamic = null;
|
||||||
|
if (__interp.variables.exists(name) && Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||||
|
return v($a{arguments});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.$name($a{arguments});
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
overrideExpr = macro {
|
||||||
|
var name:String = $v{name};
|
||||||
|
|
||||||
|
if (__interp != null) {
|
||||||
|
var v:Dynamic = null;
|
||||||
|
if (__interp != null && __interp.variables.exists(name) && Reflect.isFunction(v = __interp.variables.get(name))) {
|
||||||
|
v($a{arguments});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.$name($a{arguments});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var superFuncExpr:Expr = returns ? {
|
||||||
|
macro return super.$name($a{arguments});
|
||||||
|
} : {
|
||||||
|
macro super.$name($a{arguments});
|
||||||
|
};
|
||||||
|
|
||||||
|
var func:Function = {
|
||||||
|
ret: fun.ret,
|
||||||
|
params: fun.params.copy(),
|
||||||
|
expr: overrideExpr,
|
||||||
|
args: fun.args.copy()
|
||||||
|
};
|
||||||
|
|
||||||
|
var overrideField:Field = {
|
||||||
|
name: f.name,
|
||||||
|
access: f.access.copy(),
|
||||||
|
kind: FFun(func),
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
doc: f.doc,
|
||||||
|
meta: f.meta.copy()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!overrideField.access.contains(AOverride))
|
||||||
|
overrideField.access.push(AOverride);
|
||||||
|
|
||||||
|
var superField:Field = {
|
||||||
|
name: '$FUNC_PREFIX${f.name}',
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
kind: FFun({
|
||||||
|
ret: fun.ret,
|
||||||
|
params: fun.params.copy(),
|
||||||
|
expr: superFuncExpr,
|
||||||
|
args: fun.args.copy()
|
||||||
|
}),
|
||||||
|
access: f.access.copy()
|
||||||
|
};
|
||||||
|
if (superField.access.contains(AOverride))
|
||||||
|
superField.access.remove(AOverride);
|
||||||
|
shadowClass.fields.push(overrideField);
|
||||||
|
shadowClass.fields.push(superField);
|
||||||
|
definedFields.push(f.name);
|
||||||
|
default:
|
||||||
|
// fuck off >:(
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalFields = definedFields.length;
|
||||||
|
|
||||||
|
if(totalFields == 0 && !hasNew) {
|
||||||
|
//Sys.println(cl.pack.join(".") + "." + cl.name + ", " + totalFields);
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowClass.kind = TDClass({
|
||||||
|
pack: cl.pack.copy(),
|
||||||
|
name: cl.name
|
||||||
|
}, [
|
||||||
|
{name: "IHScriptCustomBehaviour", pack: ["hscript"]}
|
||||||
|
], false, true, false);
|
||||||
|
shadowClass.name = '${cl.name}$CLASS_SUFFIX';
|
||||||
|
var imports = Context.getLocalImports().copy();
|
||||||
|
Utils.setupMetas(shadowClass, imports);
|
||||||
|
|
||||||
|
// Adding hscript getters and setters
|
||||||
|
|
||||||
|
shadowClass.fields.push({
|
||||||
|
name: "__interp",
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
kind: FVar(TPath({
|
||||||
|
pack: ['hscript'],
|
||||||
|
name: 'Interp'
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
|
||||||
|
// Todo: make it possible to override
|
||||||
|
if(cl.name == "FunkinShader" || cl.name == "CustomShader" || cl.name == "MultiThreadedScript") {
|
||||||
|
Context.defineModule(cl.module, [shadowClass], imports);
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasHgetInSuper = false;
|
||||||
|
var hasHsetInSuper = false;
|
||||||
|
|
||||||
|
if(cl.name == "CustomShader") {
|
||||||
|
hasHgetInSuper = hasHsetInSuper = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: somehow check the super super class
|
||||||
|
for(_field in [fields.copy(), superFields.copy()])
|
||||||
|
for(f in _field) {
|
||||||
|
if (f.name == "new")
|
||||||
|
continue;
|
||||||
|
if (f.name.startsWith(FUNC_PREFIX))
|
||||||
|
continue;
|
||||||
|
if (f.access.contains(ADynamic) || f.access.contains(AStatic) || f.access.contains(AExtern))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(f.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (fun.params != null && fun.params.length > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!hasHgetInSuper)
|
||||||
|
hasHgetInSuper = f.name == "hget";
|
||||||
|
if(!hasHsetInSuper)
|
||||||
|
hasHsetInSuper = f.name == "hset";
|
||||||
|
|
||||||
|
if(hasHgetInSuper && hasHsetInSuper)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hgetField = if(hasHgetInSuper) {
|
||||||
|
macro {
|
||||||
|
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 super.hget(name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
macro {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hsetField = if(hasHsetInSuper) {
|
||||||
|
macro {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return super.hset(name, val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
macro {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(hasHsetInSuper || hasHgetInSuper) return fields;
|
||||||
|
|
||||||
|
//trace(cl.name);
|
||||||
|
|
||||||
|
shadowClass.fields.push({
|
||||||
|
name: "hset",
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
access: hasHsetInSuper ? [AOverride, APublic] : [APublic],
|
||||||
|
kind: FFun({
|
||||||
|
ret: TPath({name: 'Dynamic', pack: []}),
|
||||||
|
params: [],
|
||||||
|
expr: hsetField,
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "name",
|
||||||
|
opt: false,
|
||||||
|
meta: [],
|
||||||
|
type: TPath({name: "String", pack: []})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "val",
|
||||||
|
opt: false,
|
||||||
|
meta: [],
|
||||||
|
type: TPath({name: "Dynamic", pack: []})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
shadowClass.fields.push({
|
||||||
|
name: "hget",
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
access: hasHgetInSuper ? [AOverride, APublic] : [APublic],
|
||||||
|
kind: FFun({
|
||||||
|
ret: TPath({name: 'Dynamic', pack: []}),
|
||||||
|
params: [],
|
||||||
|
expr: hgetField,
|
||||||
|
args: [
|
||||||
|
{
|
||||||
|
name: "name",
|
||||||
|
opt: false,
|
||||||
|
meta: [],
|
||||||
|
type: TPath({name: "String", pack: []})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
/*var p = new Printer();
|
||||||
|
var aa = p.printTypeDefinition(shadowClass);
|
||||||
|
if(aa.length < 5024)
|
||||||
|
trace(aa);
|
||||||
|
if(aa.indexOf("pack") >= 0)
|
||||||
|
if(cl.name == "FunkinShader")*/
|
||||||
|
|
||||||
|
Context.defineModule(cl.module, [shadowClass], imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
class ClassExtendMacro {
|
||||||
|
public var usedClass:Class<Dynamic>;
|
||||||
|
public var className:String;
|
||||||
|
}
|
||||||
|
#end
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
package hscript.macros;
|
||||||
|
|
||||||
|
#if macro
|
||||||
|
import Type.ValueType;
|
||||||
|
import haxe.macro.ComplexTypeTools;
|
||||||
|
import haxe.macro.Expr;
|
||||||
|
import haxe.macro.Context;
|
||||||
|
import haxe.macro.Printer;
|
||||||
|
import haxe.macro.Compiler;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class UsingHandler {
|
||||||
|
public static function init() {
|
||||||
|
#if !display
|
||||||
|
if(Context.defined("display")) return;
|
||||||
|
for(apply in Config.ALLOWED_ABSTRACT_AND_ENUM) {
|
||||||
|
Compiler.addGlobalMetadata(apply, '@:build(hscript.macros.UsingHandler.build())');
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
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") && !cl.name.contains("_HSC")) {
|
||||||
|
var metas = cl.meta.get();
|
||||||
|
|
||||||
|
var trimEnum = cl.name.substr(0, cl.name.length - 6);
|
||||||
|
|
||||||
|
var key = cl.module;
|
||||||
|
var fkey = cl.module + "." + trimEnum;
|
||||||
|
if(key == "lime.system.Locale") return fields; // Error: Unknown identifier : currentLocale, Due to Func
|
||||||
|
if(key == "cpp.Function") return fields; // Error: Unknown identifier : nativeGetProcAddress, Due to Func
|
||||||
|
if(key == "haxe.ds.Vector") return fields; // Error: haxe.ds._Vector.VectorData<blit.T> has no field blit, Due to Func
|
||||||
|
if(key == "haxe.display.Display") return fields; // Error: haxe.display.DisplayItemKind<haxe.display.DisplayLiteral<Dynamic>> has no field Null, Due to Func
|
||||||
|
if(key == "cpp.Callable") return fields; // Error: cpp.Function.fromStaticFunction must be called on static function, Due to Func
|
||||||
|
if(key == "haxe.display.JsonAnonStatusKind") return fields; // Error: cannot initialize a variable of type 'char *' with an rvalue of type 'const char *', Due to Func
|
||||||
|
if(key == "cpp.CharStar") return fields; // Error: cannot initialize a variable of type 'char *' with an rvalue of type 'const char *', Due to Func
|
||||||
|
if(Config.DISALLOW_ABSTRACT_AND_ENUM.contains(cl.module) || Config.DISALLOW_ABSTRACT_AND_ENUM.contains(fkey)) return fields;
|
||||||
|
if(cl.module.contains("_")) return fields; // Weird issue, sorry
|
||||||
|
|
||||||
|
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();
|
||||||
|
Utils.setupMetas(shadowClass, imports);
|
||||||
|
//trace(cl.module);
|
||||||
|
|
||||||
|
for(f in fields)
|
||||||
|
switch(f.kind) {
|
||||||
|
case FFun(fun):
|
||||||
|
if (f.access.contains(AStatic)) {
|
||||||
|
if (fun.expr != null) {
|
||||||
|
fun.expr = macro @:privateAccess $e{fun.expr};
|
||||||
|
shadowClass.fields.push(f);
|
||||||
|
|
||||||
|
/*var trimEnum = cl.name.substr(0, cl.name.length - 6);
|
||||||
|
|
||||||
|
var returns:Bool = !fun.ret.match(TPath({name: "Void"}));
|
||||||
|
|
||||||
|
var name = f.name;
|
||||||
|
|
||||||
|
var arguments = fun.args == null ? [] : [for(a in fun.args) macro $i{a.name}];
|
||||||
|
|
||||||
|
var expr:Expr = Context.parse('${returns?"return " : ""} $trimEnum.$name(${[for(a in fun.args) a.name].join(", ")})', f.pos);
|
||||||
|
|
||||||
|
var func:Function = {
|
||||||
|
ret: fun.ret,
|
||||||
|
params: fun.params.copy(),
|
||||||
|
expr: expr,
|
||||||
|
args: fun.args.copy()
|
||||||
|
};
|
||||||
|
|
||||||
|
var field:Field = {
|
||||||
|
pos: f.pos,
|
||||||
|
name: f.name,
|
||||||
|
meta: f.meta,
|
||||||
|
kind: FFun(func),
|
||||||
|
doc: null,//f.doc,
|
||||||
|
access: [APublic, AStatic]
|
||||||
|
}
|
||||||
|
shadowClass.fields.push(field);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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(".");
|
||||||
|
|
||||||
|
//trace(pack, cl.name, name, cl.module);
|
||||||
|
|
||||||
|
if(pack[pack.length - 1] == trimEnum)
|
||||||
|
pack.pop();
|
||||||
|
|
||||||
|
var complexType:ComplexType = t;
|
||||||
|
if(complexType == null && e != null) {
|
||||||
|
complexType = switch(e.expr) {
|
||||||
|
case EConst(CRegexp(_)): TPath({ name: "EReg", pack: [] });
|
||||||
|
|
||||||
|
default: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(complexType == null) {
|
||||||
|
complexType = TPath({
|
||||||
|
name: trimEnum,
|
||||||
|
pack: [],//pack
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var code = Context.parse('@:privateAccess ($trimEnum.$name)', f.pos); // '${pack.join(".")}.${trimEnum}.$name'
|
||||||
|
|
||||||
|
var field:Field = {
|
||||||
|
pos: f.pos,
|
||||||
|
name: f.name,
|
||||||
|
meta: f.meta,
|
||||||
|
kind: FVar(null, code),
|
||||||
|
doc: f.doc,
|
||||||
|
access: [APublic, AStatic]
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowClass.fields.push(field);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
//var printer = new Printer();
|
||||||
|
//for(field in shadowClass.fields)
|
||||||
|
// trace(printer.printField(field));
|
||||||
|
|
||||||
|
Context.defineModule(cl.module, [shadowClass], imports);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#end
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
package hscript.macros;
|
||||||
|
|
||||||
|
#if macro
|
||||||
|
import haxe.macro.Type.ClassType;
|
||||||
|
import Type.ValueType;
|
||||||
|
import haxe.macro.Expr.Function;
|
||||||
|
import haxe.macro.Expr;
|
||||||
|
import haxe.macro.Type.MetaAccess;
|
||||||
|
import haxe.macro.Type.FieldKind;
|
||||||
|
import haxe.macro.Type.ClassField;
|
||||||
|
import haxe.macro.Type.VarAccess;
|
||||||
|
import haxe.macro.*;
|
||||||
|
|
||||||
|
using StringTools;
|
||||||
|
|
||||||
|
class Utils {
|
||||||
|
public 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 = [];
|
||||||
|
shadowClass.meta.push({name: ":dox", params: [macro hide], pos: Context.currentPos()});
|
||||||
|
shadowClass.meta.push({name: ":noCompletion", params: [], 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:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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