Compare commits

...
209 Commits
Author SHA1 Message Date
NeeEoo 2f2dec1634 Temp Fix for mod im working on 2023-08-13 12:02:04 +02:00
NeeEoo 51188173bb Merge To Main 2023-08-13 11:59:13 +02:00
NeeEoo d0797ad5d8 Fixed bug with redirects 2023-08-07 13:54:19 +02:00
NeeEoo 9b37bd532e Oops forgot this 2023-07-06 11:59:12 +02:00
NeeEoo 333352edcf Fix bug + bypassAccessor on assign on scriptObject 2023-07-06 00:40:21 +02:00
NeeEoo 05783773af Added support for sub class imports 2023-06-15 14:36:28 +02:00
NeeEoo 59ee20ee7a WIP Super Class Support 2023-06-15 14:21:18 +02:00
NeeEoo 87f2c1b062 Added import as and switch or and def null 2023-06-15 11:08:08 +02:00
NeeEoo b85cefea56 Cleanup 2023-04-19 13:37:08 +02:00
Yoshman29 2e28f863f3 some fixes & stuff 2023-04-19 01:46:48 +02:00
NeeEoo ddaa4d1741 Added support for dots in preprocessors 2023-04-10 15:08:16 +02:00
NeeEoo 732bd1520a Improved Custom Classes (getting fields outside of the class) 2023-04-10 14:14:16 +02:00
NeeEoo 1d67946f3f Outside variables now in classes (no more import in class) 2023-04-10 03:36:50 +02:00
Yoshman29 fab6d7e662 Merge branch 'custom-classes' of https://github.com/YoshiCrafter29/hscript-improved into custom-classes 2023-04-10 02:56:20 +02:00
NeeEoo 6e20578a81 Improved static variables 2023-04-10 02:37:41 +02:00
NeeEoo dc5282c32e Added finals 2023-04-10 02:10:46 +02:00
lunarcleint 812abae6e5 ??= op 2023-04-09 16:51:04 -07:00
NeeEoo b3b512d027 Added support for ?. 2023-04-10 00:09:50 +02:00
NeeEoo ed296c4c7f Merge branch 'master' into custom-classes 2023-04-09 23:28:45 +02:00
lunarcleint 595bb47249 ?? and .? syntax (only ?? is functional) 2023-04-09 14:09:58 -07:00
NeeEoo daad1a4fa8 Added underscore support to numbers + binary 2023-04-08 00:08:49 +02:00
Yoshman29 daef1ac198 Merge branch 'custom-classes' of https://github.com/YoshiCrafter29/hscript-improved into custom-classes 2023-04-07 16:40:23 +02:00
Yoshman29 3b9d88b252 Update Interp.hx 2023-04-07 16:40:22 +02:00
NeeEoo 809f8229b4 Implemented Super 2023-04-02 18:22:02 +02:00
Yoshman29 ffb1ee2523 Update CustomClassHandler.hx 2023-04-02 03:39:21 +02:00
Yoshman29 0903718314 removed all unnecessary traces 2023-04-01 22:46:02 +02:00
Yoshman29 e0cb883ae4 Update ClassExtendMacro.hx 2023-04-01 18:31:39 +02:00
Yoshman29 17449dd9d5 oopsie 2023-04-01 17:15:01 +02:00
Yoshman29 7963631a1d Update ClassExtendMacro.hx 2023-04-01 15:30:46 +02:00
Yoshman29 77d88f4b34 Update ClassExtendMacro.hx 2023-04-01 15:12:36 +02:00
Yoshman29 c5e3ab1162 custom classes 2023-04-01 15:02:36 +02:00
Yoshman29 75041c1db9 possible working code????? huh??? 2023-04-01 14:38:13 +02:00
Yoshman29 558a4c0782 Tried some fuckery 2023-04-01 02:23:07 +02:00
NeeEoo 995c3b9c8e ‍ 2023-03-31 22:11:48 +02:00
Yoshman29 0a64bca9ce custom class progress 2023-03-31 21:41:34 +02:00
NeeEoo b7b12b6cbb WIP Classes 2023-03-31 20:16:30 +02:00
NeeEoo 5684ca8671 WIP Class Parsing 2023-03-31 18:12:50 +02:00
NeeEoo 3c81360dc2 Merge branch 'master' into custom-classes 2023-03-31 17:03:00 +02:00
NeeEoo fc50ebdf90 Small Fix 2023-03-31 00:12:54 +02:00
Yoshman29 4d6e8db5ff helpers 2023-03-30 17:34:50 +02:00
NeeEoo 938ffac57e Custom classes, 2/? finished the macro 2023-03-19 17:57:37 +01:00
NeeEoo 50aaffb101 Custom classes, 1/? started with macros 2023-03-19 05:30:06 +01:00
NeeEoo 4f9b449c6e Added inferred map types and bypassAccessor 2023-03-19 05:26:27 +01:00
Yoshman29 c1a36a3f4b improve deez nuts 2023-01-07 22:22:05 +01:00
Yoshman29 4ca6e2a680 Fixed weird erroring with an error handling 2022-12-26 22:17:08 +01:00
Yoshman29 11db805c34 improve deez nuts 2022-12-24 13:07:02 +01:00
Yoshman29 f1f700ab69 Update UsingHandler.hx 2022-12-22 21:17:47 +01:00
Yoshman29 9eeb8ddb80 that macro took me 3 hours 2022-12-22 21:09:11 +01:00
Yoshman29 95de26a6d0 fuck 2022-12-09 23:09:28 +01:00
Yoshman29 88c2e28dbc crap 2022-12-07 23:51:03 +01:00
Yoshman29 30b7a9e4d4 Update Checker.hx 2022-12-07 23:47:37 +01:00
Yoshman29 37542065d6 bug fix (now it works as intended) 2022-11-04 20:10:35 +01:00
Yoshman29 c9608f7760 Update Interp.hx 2022-11-04 19:54:57 +01:00
Yoshman29 6ba54b0e77 static and public 2022-11-04 19:33:04 +01:00
Yoshman29 f9bb3105c8 new interface 2022-11-02 14:36:36 +01:00
Yoshman29 4b5baa9b5f Revert "thing that needs to be reverted"
This reverts commit 6dedd87260.
2022-10-13 23:18:54 +02:00
Yoshman29 6dedd87260 thing that needs to be reverted 2022-10-13 23:18:47 +02:00
Yoshman29 91317222fb Update Interp.hx 2022-08-13 03:00:11 +02:00
Yoshman29 494953a8cc Added interp.importEnabled 2022-08-12 23:40:55 +02:00
Yoshman29 ae4d8be50c more error handling + variables fix 2022-08-10 17:21:15 +02:00
Yoshman29 d34790e05c fix 2022-07-19 02:44:22 +02:00
Yoshman29 b77e15c6d6 forgot to push smh 2022-07-11 11:32:45 +02:00
Yoshman29 54195d5811 hscript updates 2022-07-02 18:21:43 +02:00
Yoshman29 9c7907f91a fixes 2022-06-30 02:03:07 +02:00
Yoshman29 0601b8def6 natural import & static access from vars for YCE 2022-06-29 00:53:51 +02:00
YoshiCrafter29 841261f199 Added import support 2022-06-08 20:10:40 +02:00
Nicolas Cannasse 7124b6c4ce fix for latest haxe 2022-04-11 17:14:38 +02:00
Nicolas Cannasse ad7beec559 fix for async idents and local functions 2022-04-01 14:43:03 +02:00
Nicolas Cannasse bd4fc51392 renamed test script 2022-04-01 10:27:20 +02:00
Nicolas Cannasse 54d994a879 added asyncIdents support 2022-03-24 15:26:50 +01:00
Nicolas Cannasse 891a085f2b fixed declared vars leak when return (close #111) 2022-01-30 11:26:32 +01:00
Nicolas Cannasse e7ccd2e72d another {} unify fix 2021-05-14 18:22:16 +02:00
Nicolas Cannasse 459a39e65d fix unification with {} 2021-05-14 18:18:55 +02:00
Jens FischerandGitHub 36eb0fca8b Fix Std.is() deprecation warnings with Haxe 4.2 (#101) 2021-03-15 19:49:07 +01:00
Nicolas Cannasse 53b9e22f26 fix for haxe 4.2 2021-02-11 12:07:30 +01:00
Nicolas Cannasse 8ff3f5e351 fixed getFields (apply params, handle interfaces) and getField (handle interface inheritance) 2020-12-18 15:58:21 +01:00
Nicolas Cannasse e6a2c443cb added support for interfaces type checking 2020-12-04 17:08:41 +01:00
Nicolas Cannasse 4f25ab162d added inheritance on setGlobals 2020-08-26 15:51:27 +02:00
Nicolas Cannasse 0520d9f187 added setVar (allow to define globals set behavior) 2020-07-30 10:22:48 +02:00
Nicolas Cannasse cc3c21b7e3 fixed unop priority overriding binop one (close #94) 2020-07-14 12:49:24 +02:00
Nicolas Cannasse ae9560124e fixed () -> e short lambda parsing (close #93) 2020-05-07 10:24:04 +02:00
Nicolas Cannasse 085f4ec37e fixed comments parsing was broken by previous fix 2020-04-27 11:19:46 +02:00
Nicolas Cannasse 476c3a9cc9 fixed parser with concat binop/unop such as a<-b or a<++b (close #92) 2020-04-26 15:10:00 +02:00
Mark KnolandGitHub 1bc5ac8768 Update haxelib.json (#83) 2020-04-12 21:32:39 +02:00
Nicolas Cannasse 4bdff11b87 removed 2020-04-10 12:21:54 +02:00
Nicolas Cannasse b32dde3c91 2.4.0 2020-04-10 10:09:34 +02:00
Nicolas Cannasse b9a566350b fixed missing enums constructor parsing 2020-04-08 15:27:03 +02:00
Nicolas Cannasse ce9ce674ea added missing unary - 2019-12-18 14:33:35 +01:00
Nicolas Cannasse b8641779bd added error on missing event args 2019-12-16 13:28:40 +01:00
Nicolas Cannasse 5e620d784e added canWrite check on fields 2019-12-13 13:18:14 +01:00
Nicolas Cannasse 013bcfaffb fixed unicode parsing in strings 2019-12-09 17:34:13 +01:00
Andy Li 2504c96927 [TravisCI] use php from apt 2019-12-04 03:48:09 +08:00
Andy Li e2f4d1481e [TravisCI] some fixes
- use bionic
 - remove flash test
 - add Haxe 4.0.3 test
 - only test C# for Haxe 4+
 - add -D php7 for Haxe 3
2019-12-04 01:01:52 +08:00
Andy Li ea3d68573b [AppVeyor] remove php and flash tests 2019-12-04 00:33:14 +08:00
Andy Li c6cb594ef1 [AppVeyor] use Haxe 4.0.3 2019-12-04 00:24:27 +08:00
Andy Li 948123bc7a keep haxe 3 support 2019-12-04 00:13:41 +08:00
Nicolas Cannasse 68f5b26af9 bugfixes for eval (close #90) 2019-12-03 14:27:07 +01:00
Nicolas Cannasse 5d493630b1 make apply public 2019-11-29 18:11:46 +01:00
Nicolas Cannasse f4db6faa80 fixed follow wrt recursion 2019-11-28 14:20:55 +01:00
Nicolas Cannasse e340f7f5ad ignored custom metadata in async toCps 2019-11-27 14:37:42 +01:00
Nicolas Cannasse b4d923b74c fixed without hscriptPos 2019-11-26 18:11:10 +01:00
Nicolas Cannasse 965f334d59 various fixes in type checker 2019-11-26 14:34:15 +01:00
Nicolas Cannasse 54463b78d2 more resumeErrors parser support, switch to parseString only (fix position with unicode) 2019-11-26 14:32:56 +01:00
Nicolas Cannasse 600aec1f50 stronger parser wrt resumeErrors 2019-11-25 20:32:08 +01:00
Nicolas Cannasse bcfbe81979 fixed pmin/pmax for resumeErrors 2019-11-20 18:14:02 +01:00
ee-tprandNicolas Cannasse 31e8851bcc Add a resetVariables into the interp so it can be called when extending interp (#89) 2019-10-30 11:51:38 +01:00
Nicolas Cannasse f464767ee7 added Parser.resumeError, added Checker.getCompletion 2019-10-20 11:16:23 +02:00
Christopher GeorgeandNicolas Cannasse 22eb58b3de Fix calling with 0 args targeting Java (#88) 2019-10-08 09:29:14 +02:00
Nicolas Cannasse 0daee20545 allow customization of top level async end point 2019-10-07 10:57:53 +02:00
Nicolas Cannasse d98073dc33 added support for mutually recursive functions 2019-10-02 16:27:35 +02:00
Nicolas Cannasse fb199e7dea added removeGlobal() 2019-10-01 18:09:41 +02:00
Christopher GeorgeandNicolas Cannasse 6cea0d97c2 Call error() on invalid number of arguments instead of just throwing … (#86) 2019-09-25 21:09:36 +02:00
Nicolas Cannasse 058dd2e01e fix for haxe 4.0-rc4 2019-09-05 10:41:37 +02:00
Nicolas Cannasse 975d122491 make unify public 2019-08-29 17:29:11 +02:00
Nicolas Cannasse eef4c66374 disable flash testing (404) 2019-06-16 10:52:29 +02:00
ncannasse 5ce4fbd74d added @sync function name(...) support, improved variable lookup 2019-04-24 15:27:20 +02:00
ncannasse f4d8cff26b disable cs tests for now (see https://github.com/HaxeFoundation/haxe/issues/4639) 2019-03-07 12:25:26 +01:00
ncannasse 46b6b3c151 always valid 2018-10-25 15:13:36 +02:00
ncannasse 796b217dec compile Checker (travis) 2018-10-15 09:42:01 +02:00
ncannasse 1ccc35f464 added try/switch type checking, and some other fixes 2018-10-15 09:40:41 +02:00
ncannasse 2ed6f15fe1 2.3.0 2018-10-08 09:46:15 +02:00
Juraj KirchheimandNicolas Cannasse 575040be65 Fix Haxe 3. (#75) 2018-09-26 18:38:29 +02:00
Juraj KirchheimandNicolas Cannasse 206959adbd Support new function type syntax. (#74) 2018-09-26 14:06:16 +02:00
ncannasse dd1c97b6af more type checking 2018-09-25 17:01:09 +02:00
ncannasse 85463dcff0 implemented apply type parameters 2018-09-25 12:04:35 +02:00
ncannasse 7ff816417e fixes 2018-09-24 15:54:40 +02:00
ncannasse 3fa2f3898a fix 2018-09-24 15:54:24 +02:00
ncannasse 514ce9eec2 more type checks 2018-09-21 10:47:30 +02:00
ncannasse 5bc357b4b3 hscriptPos changes 2018-09-21 10:47:20 +02:00
ncannasse 56ddc3c24e more typing 2018-09-20 18:21:17 +02:00
ncannasse e407b2a307 optimize the ast (eliminate (function(_) e)(null) calls)
treat function literals as synchronized by default
2018-09-19 18:45:07 +02:00
ncannasse 1ac194ed1d more typing 2018-09-19 18:42:06 +02:00
ncannasse 62bf5d4cc9 more typing, added top down inference 2018-09-19 15:11:29 +02:00
ncannasse 27093064a9 added ECheckType, added short lambda parsing 2018-09-18 16:15:15 +02:00
ncannasse 860a3018a7 don't test on haxe 3.2.x anymore 2018-09-18 15:07:07 +02:00
ncannasse eb3992dbdb separate Checker / CheckerTypes 2018-09-18 14:35:36 +02:00
ncannasse 8c5f9cc1d3 more type checking 2018-09-17 11:52:29 +02:00
ncannasse ed78703090 added type checker (partial) 2018-09-12 18:00:34 +02:00
ncannasse 29b61bcee9 fixed invalid char position 2018-09-12 18:00:34 +02:00
Andy Li 0ff49845a7 fix hscript.Bytes with -D hscriptPos (close #64) 2018-05-11 17:58:04 +08:00
Andy Li c17366b2b1 [AppVeyor] update flash install script 2018-05-11 16:39:39 +08:00
Andy Li 5da267fb31 [TravisCI] recompile hxcpp ndll for haxe 3.2.1 2018-05-11 16:18:20 +08:00
Andy Li dffa3345d0 [TravisCI] turn off php deprecated function warning 2018-05-11 16:01:16 +08:00
Andy Li a23c767fb0 [AppVeyor] enable windows update service 2018-05-11 14:05:39 +08:00
Andy Li 5d6ec51302 [CI] testing 3.4.7 2018-05-11 14:01:38 +08:00
Andy Li 585f277bf5 [TravisCI] fix homebrew php and python 2018-05-11 12:55:32 +08:00
Andy Li aae5f431cb use Bytes#getInt32 and BytesBuffer#addInt32
fix test for python and php targets
2018-05-11 11:00:40 +08:00
Andy Li 4eb84e5c32 better pos info in test 2018-05-11 10:48:14 +08:00
Nicolas Cannasse 70b11ec7ad 2.2.0 2018-04-14 12:23:12 +02:00
ncannasse f2944e0bae added rethrow() 2018-03-02 17:26:12 +01:00
ncannasse fdec33d086 support async transform with -D hscriptPos 2018-03-02 17:25:43 +01:00
ncannasse 0702074469 added ECustom error message 2018-03-02 17:22:35 +01:00
ncannasse 6d5cbf6974 correctly handle "return" in sync parts 2018-03-02 11:25:53 +01:00
Nicolas Cannasse 5429a3a4d4 added typeToString() 2018-02-04 22:50:28 +01:00
Nicolas Cannasse c124076279 added typedef parsing support 2018-02-04 20:54:08 +01:00
Nicolas Cannasse 0d1d811d2c use error instead of throw 2018-02-04 12:31:36 +01:00
ncannasse 8c04831339 don't pass return value in SReturn : big problem in JS that does a Std.string on exception value 2017-11-24 12:43:39 +01:00
ncannasse 4a8b2690aa fixed trace() with multiple arguments 2017-11-23 16:14:59 +01:00
ncannasse e2bc716ea7 fix 2017-11-23 15:05:04 +01:00
ncannasse 6c5987f9af fixed error when no inline triggered 2017-11-23 14:05:12 +01:00
ncannasse 1e79880c72 more conformance to haxe syntax wrt mandatory ;
added static and macro accessors
2017-11-23 12:40:50 +01:00
ncannasse f62d891c63 reduce OpNeg(CInt/CFloat) to negative Int/Float like haxe parser does 2017-11-23 12:17:23 +01:00
ncannasse 930cb8853c don't reset line + preprocessor fix 2017-11-23 11:34:44 +01:00
ncannasse 22104ff64e fixed preprocessor bug 2017-11-22 18:41:32 +01:00
ncannasse 17564441b5 added #if/#else support
added function arg default value expr (only if allowTypes, not supported by interp)
allowed local "inline function"
added parseModule
added exponent support in floats (1.5e-3)
2017-11-22 17:30:16 +01:00
ncannasse a9140a4403 bugfix haxe 4 2017-11-21 17:16:30 +01:00
ncannasse ce47ca0a8a fixed break & continue in sync-optimized expression 2017-11-21 15:55:38 +01:00
Alexander KuzmenkoandNicolas Cannasse 852fee170e [php] don't expect iterator to have iterator field (fixes #69) (#71)
* [php] don't expect IntIterator to have a field which does not exist (fixes #69)

* cleanup

* fix Interp.makeIterator for Haxe 3.4
2017-10-03 09:46:14 +02:00
Simon Krajewski 8463e99d13 tap that 2017-10-01 12:32:16 +02:00
Simon Krajewski 3c016b73ee semicolon 2017-10-01 12:24:41 +02:00
Simon Krajewski 8d4173b0be use php7 2017-10-01 12:22:08 +02:00
Simon Krajewski 502f043804 actually install hx3compat on the CI 2017-10-01 11:51:08 +02:00
Simon Krajewski f8571fb175 use hx3compat for haxe.unit for now 2017-10-01 11:47:58 +02:00
Nicolas Cannasse 7209aa8880 fixed @async in @sync, added scriptCall special API 2017-08-18 16:44:32 +02:00
Andy Li 1a4a1217ae haxe 3.2.1 compatibility 2017-08-17 10:35:30 +08:00
Nicolas Cannasse 139c360feb fixed parsing of @meta {} 2017-08-11 16:13:44 +02:00
Nicolas Cannasse be1afbdb5c fixes 2017-08-11 12:03:44 +02:00
Nicolas Cannasse 8a7e8c8d7d changed @async and @split 2017-08-11 12:03:35 +02:00
Nicolas Cannasse 931f79dacb move error formating to Printer 2017-08-11 11:03:29 +02:00
Nicolas Cannasse 261e6ee78e bug fixes 2017-08-11 11:03:06 +02:00
Nicolas Cannasse 9eaddcdafb license changed to MIT (close #67) 2017-08-10 16:56:31 +02:00
Nicolas Cannasse b8ede1a3e7 make sure Test include all other files to error when ast changes 2017-08-10 16:31:37 +02:00
Nicolas Cannasse bbaacd5d28 added Async 2017-08-10 16:31:10 +02:00
Nicolas Cannasse 60ed5fdfe2 added missing EMeta 2017-08-10 16:04:55 +02:00
Nicolas Cannasse 512f88c63e added EMeta support 2017-08-10 15:12:59 +02:00
Nicolas Cannasse 50c01b2cfb haxe 4 fixes 2017-08-10 15:05:38 +02:00
Nicolas Cannasse 27d3f889b5 fixed missing meta in TAnonymous 2017-07-20 11:39:24 +02:00
Nicolas Cannasse 140a9918c0 2.1.1 2017-07-19 22:14:41 +02:00
Nicolas CannasseandGitHub fc6a30b684 Update README.md 2017-07-19 21:22:33 +02:00
Nicolas CannasseandGitHub deb0ae8b8e Update README.md 2017-07-19 21:22:06 +02:00
Nicolas Cannasse 1425479569 fixed missing EMeta support 2017-07-19 21:19:20 +02:00
Nicolas Cannasse 09923651d8 2.1.0 2017-07-18 18:47:06 +02:00
Nicolas Cannasse 7ca5b85051 added optional metadata support in toplevel expr and anon types 2017-07-18 17:28:15 +02:00
Andy Li a34faf8a26 [TravisCI] use newer versions of osx and flashplayer 2017-06-27 17:24:01 +08:00
Andy Li 7708159e92 [TravisCI] haxe development tmp fix
https://github.com/HaxeFoundation/haxe/pull/6253#issuecomment-300717995
2017-05-14 00:11:15 +08:00
Andy Li 7851d48e82 [CI] test with Haxe 3.4.2 2017-05-13 23:30:51 +08:00
Andy Li f320b4fa9b [AppVeyor] fix php install 2017-05-11 09:54:17 +08:00
Andy Li b3ea81f4e8 [TravisCI] use Trusty 2017-05-11 09:38:27 +08:00
Nicolas Cannasse ace61e589d moved build scripts in /bin 2017-05-06 11:14:45 +02:00
Tom CoxonandNicolas Cannasse 51506e0400 Add filename / line number error reporting with -D hscriptPos (#57) 2017-01-02 17:48:48 +01:00
Andy Li 4a1432b01d [TravisCI] flash-player-debuger has been moved to caskroom/versions 2016-10-16 23:35:42 +08:00
Pavel AlexandrovandNicolas Cannasse aa16393c1b Add do ... while support. (#51)
Add `do ... while` support.
2016-10-03 12:24:53 +02:00
Andy Li 55ed2c0d5c Avoid using Array#sort in test.
There is some problem with the php target. Let's workaround it for now.
2016-10-01 15:14:58 +08:00
Andy Li 6c588733d9 [CI] updated flash player install 2016-10-01 12:14:25 +08:00
Andy LiandGitHub d72411632d [TravisCI] use OSX 10.10 2016-10-01 10:59:02 +08:00
romamikandNicolas Cannasse a1af1ec29e Added Map support (#49)
Map support
2016-09-28 13:04:18 +02:00
Andy Li bdd55483f9 add a line in release.bat to remind Nicolas to create a git tag 2016-08-21 22:33:13 +08:00
Nicolas Cannasse 01f3030473 2.0.7 (close #47) 2016-04-03 20:10:18 +02:00
Nicolas Cannasse 98c08becd6 fixes for -D hscriptPos 2016-04-03 20:09:39 +02:00
48 changed files with 5049 additions and 1219 deletions
+25 -29
View File
@@ -4,8 +4,11 @@ os:
- linux
- osx
dist: bionic
haxe:
- "3.2.1"
- "3.4.7"
- "4.0.3"
- development
addons:
@@ -17,44 +20,34 @@ addons:
# Python
- python3
# PHP
- php5-cli
- php-cli
- php-mbstring
# C#
- mono-devel
- mono-mcs
# Flash
- libcurl3:i386
- libglib2.0-0:i386
- libx11-6:i386
- libxext6:i386
- libxt6:i386
- libxcursor1:i386
- libnss3:i386
- libgtk2.0-0:i386
install:
# os-specific config
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
export DISPLAY=:99.0;
export AUDIODEV=null;
elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
brew update;
brew install mono;
brew install python3;
brew install php;
fi
# Download and setup a standalone flash player debugger
- haxe flash/install.hxml
# Install haxelibs
- if [ "${TRAVIS_HAXE_VERSION}" = "development" ]; then
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 tools/hxcpp; haxe compile.hxml; popd;
pushd project; neko build.n; popd;
popd;
else
haxelib install hxcpp;
fi
- haxelib install hxjava
- haxelib install hxcs
- haxelib install hx3compat
- haxelib dev hscript .
- haxelib list
@@ -62,12 +55,15 @@ script:
- pushd script &&
haxe build.hxml &&
popd
- haxe build-interp.hxml
- haxe build-neko.hxml && neko bin/Test.n
- haxe build-js.hxml && node bin/Test.js
- haxe build-java.hxml && java -jar bin/Test.jar
- haxe build-cs.hxml && mono bin/bin/Test.exe
- haxe build-cpp.hxml && ./bin/Test
- haxe build-flash.hxml -D fdb && haxe flash/run.hxml bin/Test.swf
- haxe build-php.hxml && php bin/index.php
- haxe build-python.hxml && python3 bin/Test.py
- haxe bin/build-interp.hxml
- haxe bin/build-interp.hxml -D hscriptPos
- haxe bin/build-neko.hxml && neko bin/Test.n
- haxe bin/build-js.hxml && node bin/Test.js
- haxe bin/build-java.hxml && java -jar bin/Test.jar
# 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-php.hxml -D php7 && php bin/index.php
- haxe bin/build-python.hxml && python3 bin/Test.py
+16
View File
@@ -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"
}
]
}
+16
View File
@@ -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
}
}
]
}
+22
View File
@@ -0,0 +1,22 @@
The MIT License
Copyright (C)2008-2017 Haxe Foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+16 -2
View File
@@ -64,26 +64,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.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 `hscript.Checker` in order to type check and even get completion, using `haxe -xml` output for type information.
Limitations
-----------
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)
- 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
- 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
-------
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.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
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)
+81 -4
View File
@@ -1,8 +1,14 @@
import haxe.ds.EnumValueMap;
import haxe.ds.Option;
import hscript.Macro;
import hscript.Tools;
import hscript.Async;
import hscript.Printer;
import hscript.Checker;
import haxe.unit.*;
class Test extends TestCase {
function assertScript(x,v:Dynamic,?vars : Dynamic,allowTypes=false) {
class TestHScript extends TestCase {
function assertScript(x,v:Dynamic,?vars : Dynamic, allowTypes=false, ?pos:haxe.PosInfos) {
var p = new hscript.Parser();
p.allowTypes = allowTypes;
var program = p.parseString(x);
@@ -13,7 +19,7 @@ class Test extends TestCase {
for( v in Reflect.fields(vars) )
interp.variables.set(v,Reflect.field(vars,v));
var ret : Dynamic = interp.execute(program);
assertEquals(v, ret);
assertEquals(v, ret, pos);
}
function test():Void {
@@ -73,6 +79,7 @@ class Test extends TestCase {
assertScript("(function(a,b) return a + b)(4,5)",9);
assertScript("var y = 0; var add = function(a) y += a; add(5); add(3); y", 8);
assertScript("var a = [1,[2,[3,[4,null]]]]; var t = 0; while( a != null ) { t += a[0]; a = a[1]; }; t",10);
assertScript("var a = false; do { a = true; } while (!a); a;",true);
assertScript("var t = 0; for( x in 1...10 ) t += x; t", 45);
#if haxe3
assertScript("var t = 0; for( x in new IntIterator(1,10) ) t +=x; t", 45);
@@ -93,12 +100,82 @@ class Test extends TestCase {
assertScript("var a:Array<Dynamic>=[1,2,4]; a[2]", 4, null, true);
assertScript("/**/0", 0);
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 {
var objKey = { ok:true };
var vars = {
stringMap: ["foo" => "Foo", "bar" => "Bar"],
intMap:[100 => "one hundred"],
objKey: objKey,
objMap:[objKey => "ok"],
enumKey:Option.Some("some"),
enumMap:new EnumValueMap<Option<String>, String>(),
stringIntMap: ["foo" => 100]
}
vars.enumMap.set(vars.enumKey, "ok");
assertScript('stringMap["foo"]', "Foo", vars);
assertScript('intMap[100]', "one hundred", vars);
assertScript('objMap[objKey]', "ok", vars);
assertScript('enumMap[enumKey]', "ok", vars);
assertScript('stringMap["a"] = "A"; stringMap["a"]', "A", vars);
assertScript('intMap[200] = objMap[{foo:false}] = enumMap[enumKey] = "A"', "A", vars);
assertEquals('A', vars.intMap[200]);
assertEquals('A', vars.enumMap.get(vars.enumKey));
for (key in vars.objMap.keys()) {
if (key != objKey) {
assertEquals(false, (key:Dynamic).foo);
assertEquals('A', vars.objMap[key]);
}
}
assertScript('
var keys = [];
for (key in stringMap.keys()) keys.push(key);
keys.join("_");
', {
var keys = [];
for (key in vars.stringMap.keys()) keys.push(key);
keys.join("_");
}, vars);
assertScript('stringMap.remove("foo"); stringMap.exists("foo");', false, vars);
assertScript('stringMap["foo"] = "a"; stringMap["foo"] += "b"', 'ab', vars);
assertEquals('ab', vars.stringMap['foo']);
assertScript('stringIntMap["foo"]++', 100, vars);
assertEquals(101, vars.stringIntMap['foo']);
assertScript('++stringIntMap["foo"]', 102, vars);
assertScript('var newMap = ["foo"=>"foo"]; newMap["foo"];', 'foo', vars);
#if (!php || (haxe_ver >= 3.3))
assertScript('var newMap = [enumKey=>"foo"]; newMap[enumKey];', 'foo', vars);
#end
assertScript('var newMap = [{a:"a"}=>"foo", objKey=>"bar"]; newMap[objKey];', 'bar', vars);
}
static function main() {
#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();
runner.add(new Test());
runner.add(new TestHScript());
var succeed = runner.run();
#if sys
Sys.exit(succeed ? 0 : 1);
#elseif flash
+14 -17
View File
@@ -5,20 +5,19 @@ environment:
HAXELIB_ROOT: C:\projects\haxelib
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)
- cinst haxe -version 3.2.1 -y
- cinst haxe -version 4.0.3 -y
- RefreshEnv
# Setup haxelib
- mkdir "%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
- haxelib install hxcpp > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxjava > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxcpp > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxjava > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1
- haxelib install hx3compat > log.txt || type log.txt && cmd /C exit 1
- haxelib dev hscript .
- haxelib list
@@ -28,12 +27,10 @@ test_script:
- pushd script &&
haxe build.hxml &&
popd
- haxe build-interp.hxml
- haxe build-neko.hxml && neko bin\Test.n
- haxe build-js.hxml && node bin\Test.js
- haxe build-java.hxml && java -jar bin\Test.jar
- haxe build-cs.hxml && bin\bin\Test.exe
- haxe build-cpp.hxml && bin\Test.exe
- haxe build-flash.hxml -D fdb && haxe flash\run.hxml bin\Test.swf
- haxe build-php.hxml && C:\tools\php\php.exe bin\index.php
- haxe build-python.hxml && C:\Python34-x64\python.exe bin\Test.py
- haxe bin/build-interp.hxml
- haxe bin/build-neko.hxml && neko bin\Test.n
- haxe bin/build-js.hxml && node bin\Test.js
- haxe bin/build-java.hxml && java -jar bin\Test.jar
- haxe bin/build-cs.hxml && bin\bin\Test.exe
- haxe bin/build-cpp.hxml && bin\Test.exe
- haxe bin/build-python.hxml && C:\Python34-x64\python.exe bin\Test.py
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-cpp bin
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-cs bin
+3
View File
@@ -0,0 +1,3 @@
-main TestHScript
-dce no
-lib hx3compat
+1 -1
View File
@@ -1,4 +1,4 @@
build-each.hxml
bin/build-each.hxml
-swf bin/Test.swf
-swf-header 800:600:30:FFFFFF
--flash-strict
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
--interp
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-java bin
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-js bin/Test.js
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-neko bin/Test.n
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-php bin
+2
View File
@@ -0,0 +1,2 @@
bin/build-each.hxml
-python bin/Test.py
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-cpp bin
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-cs bin
-2
View File
@@ -1,2 +0,0 @@
-main Test
-dce no
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
--interp
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-java bin
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-js bin/Test.js
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-neko bin/Test.n
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-php bin
-2
View File
@@ -1,2 +0,0 @@
build-each.hxml
-python bin/Test.py
-3
View File
@@ -1,3 +0,0 @@
*.exe
*.app
flashplayerdebugger
-77
View File
@@ -1,77 +0,0 @@
import Sys.*;
import sys.FileSystem.*;
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/19/flashplayer_19_sa_debug.dmg";
case "Windows":
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/19/flashplayer_19_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", ["install", "caskroom/cask/brew-cask"]) != 0)
throw "failed to brew install caskroom/cask/brew-cask";
if (command("brew", ["cask", "install", "flash-player-debugger", "--appdir=flash"]) != 0)
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));
}
}
-42
View File
@@ -1,42 +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("flash/Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger", [fullPath(swf)]);
case "Windows":
command("flash\\flashplayer.exe", [fullPath(swf)]);
case _:
throw "unsupported platform";
}
println(getContent(flashlog));
exit(exitCode);
}
}
-2
View File
@@ -1,2 +0,0 @@
-cp flash
--run Install
-2
View File
@@ -1,2 +0,0 @@
-cp flash
--run Run
+9 -9
View File
@@ -1,9 +1,9 @@
{
"name": "hscript",
"url": "https://github.com/HaxeFoundation/hscript",
"license": "MIT",
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
"version": "2.0.6",
"releasenote": "fixes for haxe 3.3, use property access by default",
"contributors": ["ncannasse"]
}
{
"name": "hscript",
"url": "https://github.com/HaxeFoundation/hscript",
"license": "MIT",
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
"version": "2.4.0",
"releasenote": "Haxe 4.0 final + type checking/completion (hscript.Checker)",
"contributors": ["ncannasse","HaxeFoundation"]
}
+2 -1
View File
@@ -1 +1,2 @@
build-flash.hxml
bin/build-each.hxml
-hl bin/Test.hl
-65
View File
@@ -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>
+536
View File
@@ -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);
}
}
+70 -27
View File
@@ -1,26 +1,23 @@
/*
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (C)2008-2017 Haxe Foundation
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
@@ -74,6 +71,10 @@ class Bytes {
return strings[id];
}
function doEncodeInt(v: Int) {
bout.addInt32(v);
}
function doEncodeConst( c : Const ) {
switch( c ) {
case CInt(v):
@@ -82,10 +83,7 @@ class Bytes {
bout.addByte(v);
} else {
bout.addByte(1);
bout.addByte(v & 0xFF);
bout.addByte((v >> 8) & 0xFF);
bout.addByte((v >> 16) & 0xFF);
bout.addByte(v >>> 24);
doEncodeInt(v);
}
#if !haxe3
case CInt32(v):
@@ -105,13 +103,18 @@ class Bytes {
}
}
function doDecodeInt() {
var i = bin.getInt32(pin);
pin += 4;
return i;
}
function doDecodeConst() {
return switch( bin.get(pin++) ) {
case 0:
CInt(bin.get(pin++));
case 1:
var i = bin.get(pin) | (bin.get(pin+1) << 8) | (bin.get(pin+2) << 16) | (bin.get(pin+3) << 24);
pin += 4;
var i = doDecodeInt();
CInt(i);
case 2:
CFloat( Std.parseFloat(doDecodeString()) );
@@ -130,8 +133,17 @@ class Bytes {
}
function doEncode( e : Expr ) {
#if hscriptPos
doEncodeString(e.origin);
doEncodeInt(e.line);
var e = e.e;
#end
bout.addByte(Type.enumIndex(e));
switch( e ) {
case EImport(c):
// TODO
case EClass(_, _, _, _):
// TODO
case EConst(c):
doEncodeConst(c);
case EIdent(v):
@@ -174,6 +186,9 @@ class Bytes {
case EWhile(cond,e):
doEncode(cond);
doEncode(e);
case EDoWhile(cond,e):
doEncode(cond);
doEncode(e);
case EFor(v,it,e):
doEncodeString(v);
doEncode(it);
@@ -230,10 +245,28 @@ class Bytes {
}
bout.addByte(255);
if( def == null ) bout.addByte(255) else doEncode(def);
case EMeta(name,args,e):
doEncodeString(name);
bout.addByte(args == null ? 0 : args.length + 1);
if( args != null ) for( e in args ) doEncode(e);
doEncode(e);
case ECheckType(e,_):
doEncode(e);
}
}
function doDecode() : Expr {
#if hscriptPos
if (bin.get(pin) == 255) {
pin++;
return null;
}
var origin = doDecodeString();
var line = doDecodeInt();
return { e : _doDecode(), pmin : 0, pmax : 0, origin : origin, line : line };
}
function _doDecode() : ExprDef {
#end
return switch( bin.get(pin++) ) {
case 0:
EConst( doDecodeConst() );
@@ -339,6 +372,16 @@ class Bytes {
}
var def = doDecode();
ESwitch(e, cases, def);
case 24:
var cond = doDecode();
EDoWhile(cond,doDecode());
case 25:
var name = doDecodeString();
var count = bin.get(pin++);
var args = count == 0 ? null : [for( i in 0...count - 1 ) doDecode()];
EMeta(name, args, doDecode());
case 26:
ECheckType(doDecode(), CTPath(["Void"]));
case 255:
null;
default:
@@ -357,4 +400,4 @@ class Bytes {
return b.doDecode();
}
}
}
+1241
View File
File diff suppressed because it is too large Load Diff
+105
View File
@@ -0,0 +1,105 @@
package hscript;
using StringTools;
class CustomClassHandler implements IHScriptCustomConstructor {
public static var staticHandler = new StaticHandler();
public var ogInterp:Interp;
public var name:String;
public var fields:Array<Expr>;
public var extend:String;
public var interfaces:Array<String>;
public function new(ogInterp:Interp, name:String, fields:Array<Expr>, ?extend:String, ?interfaces:Array<String>) {
this.ogInterp = ogInterp;
this.name = name;
this.fields = fields;
this.extend = extend;
this.interfaces = interfaces;
}
public function hnew(args:Array<Dynamic>):Dynamic {
var interp = new Interp();
interp.errorHandler = ogInterp.errorHandler;
var cl = extend == null ? TemplateClass : Type.resolveClass('${extend}_HSX');
var _class = Type.createInstance(cl, args);
var __capturedLocals = ogInterp.duplicate(ogInterp.locals);
var capturedLocals:Map<String, {r:Dynamic, depth:Int}> = [];
for(k=>e in __capturedLocals)
if (e != null && e.depth <= 0)
capturedLocals.set(k, e);
var disallowCopy = Type.getInstanceFields(cl);
//trace("Locals");
for (key => value in capturedLocals) {
if(!disallowCopy.contains(key)) {
interp.locals.set(key, {r: value, depth: -1});
//trace(key, value);
}
}
//trace("Variables");
for (key => value in ogInterp.variables) {
if(!disallowCopy.contains(key)) {
interp.variables.set(key, value);
//trace(key, value);
}
}
for(expr in fields) {
@:privateAccess
interp.exprReturn(expr);
}
interp.variables.set("super", staticHandler);
_class.__interp = interp;
interp.scriptObject = _class;
var newFunc = interp.variables.get("new");
if(newFunc != null) {
Reflect.callMethod(null, newFunc, args);
}
for(variable => value in interp.variables) {
if(variable == "this") continue;
}
return _class;
}
public function toString():String {
return name;
}
}
class TemplateClass implements IHScriptCustomBehaviour {
public var __interp:Interp;
public function hset(name:String, val:Dynamic):Dynamic {
if(this.__interp.variables.exists("set_" + name)) {
return this.__interp.variables.get("set_" + name)(val); // TODO: Prevent recursion from setting it in the function
}
if (this.__interp.variables.exists(name)) {
this.__interp.variables.set(name, val);
return val;
}
Reflect.setProperty(this, name, val);
return Reflect.field(this, name);
}
public function hget(name:String):Dynamic {
if(this.__interp.variables.exists("get_" + name))
return this.__interp.variables.get("get_" + name)();
if (this.__interp.variables.exists(name))
return this.__interp.variables.get(name);
return Reflect.getProperty(this, name);
}
}
class StaticHandler {
public function new() {}
}
+109 -28
View File
@@ -1,26 +1,23 @@
/*
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (C)2008-2017 Haxe Foundation
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
@@ -38,17 +35,20 @@ typedef Expr = {
var e : ExprDef;
var pmin : Int;
var pmax : Int;
var origin : String;
var line : Int;
}
enum ExprDef {
#else
typedef ExprDef = Expr;
enum Expr {
#end
EConst( c : Const );
EIdent( v : String );
EVar( n : String, ?t : CType, ?e : Expr );
EVar( n : String, ?t : CType, ?e : Expr, ?isPublic : Bool, ?isStatic : Bool );
EParent( e : Expr );
EBlock( e : Array<Expr> );
EField( e : Expr, f : String );
EField( e : Expr, f : String , ?safe : Bool );
EBinop( op : String, e1 : Expr, e2 : Expr );
EUnop( op : String, prefix : Bool, e : Expr );
ECall( e : Expr, params : Array<Expr> );
@@ -57,25 +57,35 @@ enum Expr {
EFor( v : String, it : Expr, e : Expr );
EBreak;
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 );
EArray( e : Expr, index : Expr );
EArrayDecl( e : Array<Expr> );
EArrayDecl( e : Array<Expr>, ?wantedType: CType );
ENew( cl : String, params : Array<Expr> );
EThrow( e : Expr );
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
EObject( fl : Array<{ name : String, e : Expr }> );
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr);
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr );
EDoWhile( cond : Expr, e : Expr);
EMeta( name : String, args : Array<Expr>, e : Expr );
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 {
CTPath( path : Array<String>, ?params : Array<CType> );
CTFun( args : Array<CType>, ret : CType );
CTAnon( fields : Array<{ name : String, t : CType }> );
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
CTParent( t : CType );
CTOpt( t : CType );
CTNamed( n : String, t : CType );
}
#if hscriptPos
@@ -83,10 +93,17 @@ class Error {
public var e : ErrorDef;
public var pmin : Int;
public var pmax : Int;
public function new(e, pmin, pmax) {
public var origin : String;
public var line : Int;
public function new(e, pmin, pmax, origin, line) {
this.e = e;
this.pmin = pmin;
this.pmax = pmax;
this.origin = origin;
this.line = line;
}
public function toString(): String {
return Printer.errorToString(this);
}
}
enum ErrorDef {
@@ -97,8 +114,72 @@ enum Error {
EUnexpected( s : String );
EUnterminatedString;
EUnterminatedComment;
EInvalidPreprocessor( msg : String );
EUnknownVariable( v : String );
EInvalidIterator( v : String );
EInvalidOp( op : String );
EInvalidAccess( f : String );
ECustom( msg : String );
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>;
}
+6
View File
@@ -0,0 +1,6 @@
package hscript;
interface IHScriptCustomBehaviour {
public function hset(name:String, val:Dynamic):Dynamic;
public function hget(name:String):Dynamic;
}
+5
View File
@@ -0,0 +1,5 @@
package hscript;
interface IHScriptCustomConstructor {
public function hnew(args:Array<Dynamic>):Dynamic;
}
+871 -411
View File
File diff suppressed because it is too large Load Diff
+54 -31
View File
@@ -1,26 +1,23 @@
/*
* Copyright (c) 2011, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Copyright (C)2008-2017 Haxe Foundation
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr.Error;
@@ -79,6 +76,11 @@ class Macro {
#if haxe3
case OpArrow: "=>";
#end
#if (haxe_ver >= 4)
case OpIn: "in";
#end
default:
continue;
};
binops.set(str, op);
if( assign )
@@ -92,6 +94,9 @@ class Macro {
case OpNegBits: "~";
case OpIncrement: "++";
case OpDecrement: "--";
#if (haxe_ver >= 4.2)
case OpSpread: continue;
#end
}
unops.set(str, op);
}
@@ -113,6 +118,7 @@ class Macro {
function convertType( t : Expr.CType ) : ComplexType {
return switch( t ) {
case CTOpt(t): TOptional(convertType(t));
case CTPath(pack, args):
var params = [];
if( args != null )
@@ -127,10 +133,18 @@ class Macro {
case CTParent(t): TParent(convertType(t));
case CTFun(args, 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):
var tf = [];
for( f in fields )
tf.push( { name : f.name, meta : [], doc : null, access : [], kind : FVar(convertType(f.t),null), pos : p } );
for( f in fields ) {
var meta = f.meta == null ? [] : [for( m in f.meta ) { name : m.name, params : m.params == null ? [] : [for( e in m.params ) convert(e)], pos : p }];
tf.push( { name : f.name, meta : meta, doc : null, access : [], kind : FVar(convertType(f.t), null), pos : p } );
}
TAnonymous(tf);
};
}
@@ -180,14 +194,18 @@ class Macro {
EIf(convert(c), convert(e1), e2 == null ? null : convert(e2));
case EWhile(c, e):
EWhile(convert(c), convert(e), true);
#if (haxe_211 || haxe3)
case EDoWhile(c, e):
EWhile(convert(c), convert(e), false);
case EFor(v, it, efor):
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#else
case EFor(v, it, e):
EFor(v, convert(it), convert(e));
#end
#if (haxe_ver >= 4)
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EBinop(OpIn,{ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#elseif (haxe_211 || haxe3)
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#else
EFor(v, convert(it), convert(efor));
#end
case EBreak:
EBreak;
case EContinue:
@@ -201,7 +219,7 @@ class Macro {
opt : false,
value : null,
});
EFunction(name, {
EFunction(#if haxe4 FNamed(name,false) #else name #end, {
params : [],
args : targs,
expr : convert(e),
@@ -229,7 +247,12 @@ class Macro {
ETernary(convert(cond), convert(e1), convert(e2));
case ESwitch(e, cases, edef):
ESwitch(convert(e), [for( c in cases ) { values : [for( v in c.values ) convert(v)], expr : convert(c.expr) } ], edef == null ? null : convert(edef));
case EMeta(m, params, esub):
var mpos = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EMeta({ name : m, params : params == null ? [] : [for( p in params ) convert(p)], pos : mpos }, convert(esub));
case ECheckType(e, t):
ECheckType(convert(e), convertType(t));
}, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end }
}
}
}
+1351 -440
View File
File diff suppressed because it is too large Load Diff
+118 -6
View File
@@ -1,3 +1,24 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
@@ -16,10 +37,20 @@ class Printer {
return buf.toString();
}
public function typeToString( t : CType ) {
buf = new StringBuf();
tabs = "";
type(t);
return buf.toString();
}
inline function add<T>(s:T) buf.add(s);
function type( t : CType ) {
switch( t ) {
case CTOpt(t):
add('?');
type(t);
case CTPath(path, params):
add(path.join("."));
if( params != null ) {
@@ -31,6 +62,19 @@ class Printer {
}
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):
if( args.length == 0 )
add("Void -> ");
@@ -70,6 +114,25 @@ class Printer {
return;
}
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):
switch( c ) {
case CInt(i): add(i);
@@ -78,7 +141,7 @@ class Printer {
}
case EIdent(v):
add(v);
case EVar(n, t, e):
case EVar(n, t, e): // TODO: static, public, override
add("var " + n);
addType(t);
if( e != null ) {
@@ -101,9 +164,9 @@ class Printer {
tabs = tabs.substr(1);
add("}");
}
case EField(e, f):
case EField(e, f, s):
expr(e);
add("." + f);
add((s == true ? "?." : ".") + f);
case EBinop(op, e1, e2):
expr(e1);
add(" " + op + " ");
@@ -148,6 +211,12 @@ class Printer {
expr(cond);
add(" ) ");
expr(e);
case EDoWhile(cond,e):
add("do ");
expr(e);
add(" while ( ");
expr(cond);
add(" )");
case EFor(v, it, e):
add("for( "+v+" in ");
expr(it);
@@ -157,7 +226,7 @@ class Printer {
add("break");
case EContinue:
add("continue");
case EFunction(params, e, name, ret):
case EFunction(params, e, name, ret): // TODO: static, public, override
add("function");
if( name != null )
add(" " + name);
@@ -184,7 +253,7 @@ class Printer {
add("[");
expr(index);
add("]");
case EArrayDecl(el):
case EArrayDecl(el, _):
add("[");
var first = true;
for( e in el ) {
@@ -252,6 +321,26 @@ class Printer {
add(";\n");
}
add("}");
case EMeta(name, args, e):
add("@");
add(name);
if( args != null && args.length > 0 ) {
add("(");
var first = true;
for( a in args ) {
if( first ) first = false else add(", ");
expr(e);
}
add(")");
}
add(" ");
expr(e);
case ECheckType(e, t):
add("(");
expr(e);
add(" : ");
addType(t);
add(")");
}
}
@@ -259,4 +348,27 @@ class Printer {
return new Printer().exprToString(e);
}
}
public static function errorToString( e : Expr.Error ) {
var message = switch( #if hscriptPos e.e #else e #end ) {
case EInvalidChar(c): "Invalid character: '"+(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
}
}
+52 -4
View File
@@ -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;
import hscript.Expr;
class Tools {
public static function iter( e : Expr, f : Expr -> Void ) {
switch( e ) {
switch( expr(e) ) {
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 EParent(e): f(e);
case EBlock(el): for( e in el ) f(e);
@@ -15,6 +38,7 @@ class Tools {
case ECall(e, args): f(e); for( a in args ) f(a);
case EIf(c, e1, e2): f(c); f(e1); if( e2 != null ) f(e2);
case EWhile(c, e): f(c); f(e);
case EDoWhile(c, e): f(c); f(e);
case EFor(_, it, e): f(it); f(e);
case EBreak,EContinue:
case EFunction(_, e, _, _): f(e);
@@ -33,12 +57,15 @@ class Tools {
f(c.expr);
}
if( def != null ) f(def);
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
case ECheckType(e,_): f(e);
}
}
public static function map( e : Expr, f : Expr -> Expr ) {
return switch( e ) {
case EConst(_), EIdent(_): e;
var edef = switch( expr(e) ) {
case EConst(_), EIdent(_), EBreak, EContinue: expr(e);
case EVar(n, t, e): EVar(n, t, if( e != null ) f(e) else null);
case EParent(e): EParent(f(e));
case EBlock(el): EBlock([for( e in el ) f(e)]);
@@ -48,8 +75,8 @@ class Tools {
case ECall(e, args): ECall(f(e),[for( a in args ) f(a)]);
case EIf(c, e1, e2): EIf(f(c),f(e1),if( e2 != null ) f(e2) else null);
case EWhile(c, e): EWhile(f(c),f(e));
case EDoWhile(c, e): EDoWhile(f(c),f(e));
case EFor(v, it, e): EFor(v, f(it), f(e));
case EBreak, EContinue: e;
case EFunction(args, e, name, t): EFunction(args, f(e), name, t);
case EReturn(e): EReturn(if( e != null ) f(e) else null);
case EArray(e, i): EArray(f(e),f(i));
@@ -60,7 +87,28 @@ class Tools {
case EObject(fl): EObject([for( fi in fl ) { name : fi.name, e : f(fi.e) }]);
case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2));
case ESwitch(e, cases, def): ESwitch(f(e), [for( c in cases ) { values : [for( v in c.values ) f(v)], expr : f(c.expr) } ], def == null ? null : f(def));
case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e));
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
}
}
+308
View File
@@ -0,0 +1,308 @@
package hscript;
import Type.ValueType;
import haxe.macro.ComplexTypeTools;
#if macro
import haxe.macro.Expr;
import haxe.macro.Context;
import haxe.macro.Printer;
import haxe.macro.Compiler;
using StringTools;
class UsingHandler {
public var usedClass:Class<Dynamic>;
public var className:String;
public function new(className:String, usedClass:Class<Dynamic>) {
this.className = className;
this.usedClass = usedClass;
}
public static function init() {
Compiler.addGlobalMetadata('flixel', '@:build(hscript.UsingHandler.build())');
Compiler.addGlobalMetadata('openfl.display.BlendMode', '@:build(hscript.UsingHandler.build())');
}
public static function build():Array<Field> {
var fields = Context.getBuildFields();
var clRef = Context.getLocalClass();
if (clRef == null) return fields;
var cl = clRef.get();
if (/* cl.name.startsWith("Flx") && */ cl.name.endsWith("_Impl_") && cl.params.length <= 0 && !cl.meta.has(":multiType")) {
var metas = cl.meta.get();
var shadowClass = macro class {
};
shadowClass.kind = TDClass();
shadowClass.params = switch(cl.params.length) {
case 0:
null;
case 1:
[
{
name: "T",
}
];
default:
[for(k=>e in cl.params) {
name: "T" + Std.int(k+1)
}];
};
shadowClass.name = '${cl.name.substr(0, cl.name.length - 6)}_HSC';
var imports = Context.getLocalImports().copy();
setupMetas(shadowClass, imports);
for(f in fields)
switch(f.kind) {
case FFun(fun):
if (f.access.contains(AStatic)) {
if (fun.expr != null)
shadowClass.fields.push(f);
}
case FProp(get, set, t, e):
if (get == "default" && (set == "never" || set == "null"))
shadowClass.fields.push(f);
case FVar(t, e):
if (f.access.contains(AStatic) || cl.meta.has(":enum") || f.name.toUpperCase() == f.name) {
var name:String = f.name;
var enumType:String = cl.name;
var pack = cl.module.split(".");
pack.pop();
var complexType:ComplexType = t != null ? t : (name.contains("REGEX") ? TPath({
name: "EReg",
pack: []
}) : TPath({
name: cl.name.substr(0, cl.name.length - 6),
pack: pack}));
var field:Field = {
pos: f.pos,
name: f.name,
meta: f.meta,
kind: FVar(complexType, {
pos: Context.currentPos(),
expr: ECast(e, complexType)
}),
doc: f.doc,
access: [APublic, AStatic]
}
shadowClass.fields.push(field);
}
default:
}
Context.defineModule(cl.module + "_HSC", [shadowClass], imports);
}
return fields;
}
static function fixStdTypes(type:ComplexType) {
switch(type) {
case TPath({name: "StdTypes"}):
var a:TypePath = type.getParameters()[0];
a.name = a.sub;
a.sub = null;
default:
}
return type;
}
public static function setupMetas(shadowClass:TypeDefinition, imports) {
shadowClass.meta = [{
name: ':dox',
pos: Context.currentPos(),
params: [
{
expr: EConst(CIdent("hide")),
pos: Context.currentPos()
}
]
}];
var module = Context.getModule(Context.getLocalModule());
for(t in module) {
switch(t) {
case TInst(t, params):
if (t != null) {
var e = t.get();
processModule(shadowClass, e.module, e.name);
processImport(imports, e.module, e.name);
}
case TEnum(t, params):
if (t != null) {
var e = t.get();
processModule(shadowClass, e.module, e.name);
processImport(imports, e.module, e.name);
}
case TType(t, params):
if (t != null) {
var e = t.get();
processModule(shadowClass, e.module, e.name);
processImport(imports, e.module, e.name);
}
case TAbstract(t, params):
if (t != null) {
var e = t.get();
processModule(shadowClass, e.module, e.name);
processImport(imports, e.module, e.name);
}
default:
// not needed?
}
}
}
public static function processModule(shadowClass:TypeDefinition, module:String, n:String) {
if (n.endsWith("_Impl_"))
n = n.substr(0, n.length - 6);
if (module.endsWith("_Impl_"))
module = module.substr(0, module.length - 6);
shadowClass.meta.push(
{
name: ':access',
params: [
Context.parse(fixModuleName(module.endsWith('.${n}') ? module : '${module}.${n}'), Context.currentPos())
],
pos: Context.currentPos()
}
);
}
/*public static function getModuleName(path:Type) {
switch(path) {
case TPath(name, pack):// | TDClass(name, pack):
var str = "";
for(p in pack) {
str += p + ".";
}
str += name;
return str;
default:
}
return "INVALID";
}*/
public static function fixModuleName(name:String) {
return [for(s in name.split(".")) if (s.charAt(0) == "_") s.substr(1) else s].join(".");
}
public static function processImport(imports:Array<ImportExpr>, module:String, n:String) {
if (n.endsWith("_Impl_"))
n = n.substr(0, n.length - 6);
module = fixModuleName(module);
if (module.endsWith("_Impl_"))
module = module.substr(0, module.length - 6);
imports.push({
path: [for(m in module.split(".")) {
name: m,
pos: Context.currentPos()
}],
mode: INormal
});
}
public static function cleanExpr(expr:Expr, oldFunc:String, newFunc:String) {
if (expr == null) return;
if (expr.expr == null) return;
switch(expr.expr) {
case EConst(c):
switch(c) {
case CIdent(s):
if (s == oldFunc)
expr.expr = EConst(CIdent(newFunc));
case CString(s, b):
if (s == oldFunc)
expr.expr = EConst(CString(s, b));
default:
// nothing
}
case EField(e, field):
if (field == oldFunc && e != null) {
switch(e.expr) {
case EConst(c):
switch(c) {
case CIdent(s):
if (s == "super")
expr.expr = EField(e, newFunc);
default:
}
default:
}
}
case EParenthesis(e):
cleanExpr(e, oldFunc, newFunc);
case EObjectDecl(fields):
for(f in fields) {
cleanExpr(f.expr, oldFunc, newFunc);
}
case EArrayDecl(values):
for(a in values) {
cleanExpr(a, oldFunc, newFunc);
}
case ECall(e, params):
cleanExpr(e, oldFunc, newFunc);
case EBlock(exprs):
for(e in exprs)
cleanExpr(e, oldFunc, newFunc);
case EFor(it, expr):
cleanExpr(it, oldFunc, newFunc);
cleanExpr(expr, oldFunc, newFunc);
case EIf(econd, eif, eelse):
cleanExpr(econd, oldFunc, newFunc);
cleanExpr(eif, oldFunc, newFunc);
cleanExpr(eelse, oldFunc, newFunc);
case EWhile(econd, e, normalWhile):
cleanExpr(econd, oldFunc, newFunc);
cleanExpr(e, oldFunc, newFunc);
case ECast(e, t):
cleanExpr(e, oldFunc, newFunc);
case ECheckType(e, t):
cleanExpr(e, oldFunc, newFunc);
case ETry(e, catches):
cleanExpr(e, oldFunc, newFunc);
for(c in catches) {
cleanExpr(c.expr, oldFunc, newFunc);
}
case EThrow(e):
cleanExpr(e, oldFunc, newFunc);
case ETernary(econd, eif, eelse):
cleanExpr(econd, oldFunc, newFunc);
cleanExpr(eif, oldFunc, newFunc);
cleanExpr(eelse, oldFunc, newFunc);
case ESwitch(e, cases, edef):
cleanExpr(e, oldFunc, newFunc);
for(c in cases) {
cleanExpr(c.expr, oldFunc, newFunc);
}
cleanExpr(edef, oldFunc, newFunc);
case EReturn(e):
cleanExpr(e, oldFunc, newFunc);
case EIs(e, t):
cleanExpr(e, oldFunc, newFunc);
case EVars(vars):
for(v in vars) {
cleanExpr(v.expr, oldFunc, newFunc);
}
case ENew(t, params):
for(p in params) {
cleanExpr(p, oldFunc, newFunc);
}
default:
}
}
}
#else
class UsingHandler {
public var usedClass:Class<Dynamic>;
public var className:String;
}
#end
+2
View File
@@ -1,4 +1,5 @@
@echo off
set PATH="C:\Program Files\7-Zip";%PATH%
rm -rf release
mkdir release
cp haxelib.json README.md extraParams.hxml release
@@ -15,4 +16,5 @@ haxe -xml release/haxedoc.xml hscript.Interp hscript.Parser hscript.Bytes hscrip
7z a -tzip release.zip release
rm -rf release
haxelib submit release.zip
echo Remember to "git tag vX.Y.Z && git push --tags"
pause